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, \
80*56a26fc1SMark Johnston VM_RTC_GETTIME, \
81*56a26fc1SMark Johnston VM_GET_GPA_PMAP, \
82*56a26fc1SMark Johnston VM_GLA2GPA, \
83*56a26fc1SMark Johnston VM_SET_INTINFO, \
84*56a26fc1SMark Johnston VM_GET_INTINFO, \
85*56a26fc1SMark Johnston VM_RESTART_INSTRUCTION, \
86*56a26fc1SMark Johnston VM_SNAPSHOT_REQ, \
87*56a26fc1SMark Johnston VM_RESTORE_TIME
887f00e46bSMark Johnston
897f00e46bSMark Johnston const cap_ioctl_t vm_ioctl_cmds[] = {
907f00e46bSMark Johnston VM_COMMON_IOCTLS,
917f00e46bSMark Johnston VM_PPT_IOCTLS,
927f00e46bSMark Johnston VM_MD_IOCTLS,
937f00e46bSMark Johnston };
947f00e46bSMark Johnston size_t vm_ioctl_ncmds = nitems(vm_ioctl_cmds);
957f00e46bSMark Johnston
96e4656e10SMark Johnston int
vm_set_desc(struct vcpu * vcpu,int reg,uint64_t base,uint32_t limit,uint32_t access)97e4656e10SMark Johnston vm_set_desc(struct vcpu *vcpu, int reg,
98e4656e10SMark Johnston uint64_t base, uint32_t limit, uint32_t access)
99e4656e10SMark Johnston {
100e4656e10SMark Johnston int error;
101e4656e10SMark Johnston struct vm_seg_desc vmsegdesc;
102e4656e10SMark Johnston
103e4656e10SMark Johnston bzero(&vmsegdesc, sizeof(vmsegdesc));
104e4656e10SMark Johnston vmsegdesc.regnum = reg;
105e4656e10SMark Johnston vmsegdesc.desc.base = base;
106e4656e10SMark Johnston vmsegdesc.desc.limit = limit;
107e4656e10SMark Johnston vmsegdesc.desc.access = access;
108e4656e10SMark Johnston
109e4656e10SMark Johnston error = vcpu_ioctl(vcpu, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
110e4656e10SMark Johnston return (error);
111e4656e10SMark Johnston }
112e4656e10SMark Johnston
113e4656e10SMark Johnston int
vm_get_desc(struct vcpu * vcpu,int reg,uint64_t * base,uint32_t * limit,uint32_t * access)114e4656e10SMark Johnston vm_get_desc(struct vcpu *vcpu, int reg, uint64_t *base, uint32_t *limit,
115e4656e10SMark Johnston uint32_t *access)
116e4656e10SMark Johnston {
117e4656e10SMark Johnston int error;
118e4656e10SMark Johnston struct vm_seg_desc vmsegdesc;
119e4656e10SMark Johnston
120e4656e10SMark Johnston bzero(&vmsegdesc, sizeof(vmsegdesc));
121e4656e10SMark Johnston vmsegdesc.regnum = reg;
122e4656e10SMark Johnston
123e4656e10SMark Johnston error = vcpu_ioctl(vcpu, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
124e4656e10SMark Johnston if (error == 0) {
125e4656e10SMark Johnston *base = vmsegdesc.desc.base;
126e4656e10SMark Johnston *limit = vmsegdesc.desc.limit;
127e4656e10SMark Johnston *access = vmsegdesc.desc.access;
128e4656e10SMark Johnston }
129e4656e10SMark Johnston return (error);
130e4656e10SMark Johnston }
131e4656e10SMark Johnston
132e4656e10SMark Johnston int
vm_get_seg_desc(struct vcpu * vcpu,int reg,struct seg_desc * seg_desc)133e4656e10SMark Johnston vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *seg_desc)
134e4656e10SMark Johnston {
135e4656e10SMark Johnston int error;
136e4656e10SMark Johnston
137e4656e10SMark Johnston error = vm_get_desc(vcpu, reg, &seg_desc->base, &seg_desc->limit,
138e4656e10SMark Johnston &seg_desc->access);
139e4656e10SMark Johnston return (error);
140e4656e10SMark Johnston }
141e4656e10SMark Johnston
142e4656e10SMark Johnston int
vm_lapic_irq(struct vcpu * vcpu,int vector)143e4656e10SMark Johnston vm_lapic_irq(struct vcpu *vcpu, int vector)
144e4656e10SMark Johnston {
145e4656e10SMark Johnston struct vm_lapic_irq vmirq;
146e4656e10SMark Johnston
147e4656e10SMark Johnston bzero(&vmirq, sizeof(vmirq));
148e4656e10SMark Johnston vmirq.vector = vector;
149e4656e10SMark Johnston
150e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_LAPIC_IRQ, &vmirq));
151e4656e10SMark Johnston }
152e4656e10SMark Johnston
153e4656e10SMark Johnston int
vm_lapic_local_irq(struct vcpu * vcpu,int vector)154e4656e10SMark Johnston vm_lapic_local_irq(struct vcpu *vcpu, int vector)
155e4656e10SMark Johnston {
156e4656e10SMark Johnston struct vm_lapic_irq vmirq;
157e4656e10SMark Johnston
158e4656e10SMark Johnston bzero(&vmirq, sizeof(vmirq));
159e4656e10SMark Johnston vmirq.vector = vector;
160e4656e10SMark Johnston
161e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_LAPIC_LOCAL_IRQ, &vmirq));
162e4656e10SMark Johnston }
163e4656e10SMark Johnston
164e4656e10SMark Johnston int
vm_lapic_msi(struct vmctx * ctx,uint64_t addr,uint64_t msg)165e4656e10SMark Johnston vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
166e4656e10SMark Johnston {
167e4656e10SMark Johnston struct vm_lapic_msi vmmsi;
168e4656e10SMark Johnston
169e4656e10SMark Johnston bzero(&vmmsi, sizeof(vmmsi));
170e4656e10SMark Johnston vmmsi.addr = addr;
171e4656e10SMark Johnston vmmsi.msg = msg;
172e4656e10SMark Johnston
173e4656e10SMark Johnston return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
174e4656e10SMark Johnston }
175e4656e10SMark Johnston
176e4656e10SMark Johnston int
vm_raise_msi(struct vmctx * ctx,uint64_t addr,uint64_t msg,int bus __unused,int slot __unused,int func __unused)1771855002dSMark Johnston vm_raise_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg,
1781855002dSMark Johnston int bus __unused, int slot __unused, int func __unused)
1791855002dSMark Johnston {
1801855002dSMark Johnston return (vm_lapic_msi(ctx, addr, msg));
1811855002dSMark Johnston }
1821855002dSMark Johnston
1831855002dSMark Johnston int
vm_apicid2vcpu(struct vmctx * ctx __unused,int apicid)184e4656e10SMark Johnston vm_apicid2vcpu(struct vmctx *ctx __unused, int apicid)
185e4656e10SMark Johnston {
186e4656e10SMark Johnston /*
187e4656e10SMark Johnston * The apic id associated with the 'vcpu' has the same numerical value
188e4656e10SMark Johnston * as the 'vcpu' itself.
189e4656e10SMark Johnston */
190e4656e10SMark Johnston return (apicid);
191e4656e10SMark Johnston }
192e4656e10SMark Johnston
193e4656e10SMark Johnston int
vm_ioapic_assert_irq(struct vmctx * ctx,int irq)194e4656e10SMark Johnston vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
195e4656e10SMark Johnston {
196e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq;
197e4656e10SMark Johnston
198e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
199e4656e10SMark Johnston ioapic_irq.irq = irq;
200e4656e10SMark Johnston
201e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
202e4656e10SMark Johnston }
203e4656e10SMark Johnston
204e4656e10SMark Johnston int
vm_ioapic_deassert_irq(struct vmctx * ctx,int irq)205e4656e10SMark Johnston vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
206e4656e10SMark Johnston {
207e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq;
208e4656e10SMark Johnston
209e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
210e4656e10SMark Johnston ioapic_irq.irq = irq;
211e4656e10SMark Johnston
212e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
213e4656e10SMark Johnston }
214e4656e10SMark Johnston
215e4656e10SMark Johnston int
vm_ioapic_pulse_irq(struct vmctx * ctx,int irq)216e4656e10SMark Johnston vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
217e4656e10SMark Johnston {
218e4656e10SMark Johnston struct vm_ioapic_irq ioapic_irq;
219e4656e10SMark Johnston
220e4656e10SMark Johnston bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
221e4656e10SMark Johnston ioapic_irq.irq = irq;
222e4656e10SMark Johnston
223e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
224e4656e10SMark Johnston }
225e4656e10SMark Johnston
226e4656e10SMark Johnston int
vm_ioapic_pincount(struct vmctx * ctx,int * pincount)227e4656e10SMark Johnston vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
228e4656e10SMark Johnston {
229e4656e10SMark Johnston
230e4656e10SMark Johnston return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
231e4656e10SMark Johnston }
232e4656e10SMark Johnston
233e4656e10SMark Johnston int
vm_isa_assert_irq(struct vmctx * ctx,int atpic_irq,int ioapic_irq)234e4656e10SMark Johnston vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
235e4656e10SMark Johnston {
236e4656e10SMark Johnston struct vm_isa_irq isa_irq;
237e4656e10SMark Johnston
238e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq));
239e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq;
240e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq;
241e4656e10SMark Johnston
242e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
243e4656e10SMark Johnston }
244e4656e10SMark Johnston
245e4656e10SMark Johnston int
vm_isa_deassert_irq(struct vmctx * ctx,int atpic_irq,int ioapic_irq)246e4656e10SMark Johnston vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
247e4656e10SMark Johnston {
248e4656e10SMark Johnston struct vm_isa_irq isa_irq;
249e4656e10SMark Johnston
250e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq));
251e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq;
252e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq;
253e4656e10SMark Johnston
254e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
255e4656e10SMark Johnston }
256e4656e10SMark Johnston
257e4656e10SMark Johnston int
vm_isa_pulse_irq(struct vmctx * ctx,int atpic_irq,int ioapic_irq)258e4656e10SMark Johnston vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
259e4656e10SMark Johnston {
260e4656e10SMark Johnston struct vm_isa_irq isa_irq;
261e4656e10SMark Johnston
262e4656e10SMark Johnston bzero(&isa_irq, sizeof(struct vm_isa_irq));
263e4656e10SMark Johnston isa_irq.atpic_irq = atpic_irq;
264e4656e10SMark Johnston isa_irq.ioapic_irq = ioapic_irq;
265e4656e10SMark Johnston
266e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
267e4656e10SMark Johnston }
268e4656e10SMark Johnston
269e4656e10SMark Johnston int
vm_isa_set_irq_trigger(struct vmctx * ctx,int atpic_irq,enum vm_intr_trigger trigger)270e4656e10SMark Johnston vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
271e4656e10SMark Johnston enum vm_intr_trigger trigger)
272e4656e10SMark Johnston {
273e4656e10SMark Johnston struct vm_isa_irq_trigger isa_irq_trigger;
274e4656e10SMark Johnston
275e4656e10SMark Johnston bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
276e4656e10SMark Johnston isa_irq_trigger.atpic_irq = atpic_irq;
277e4656e10SMark Johnston isa_irq_trigger.trigger = trigger;
278e4656e10SMark Johnston
279e4656e10SMark Johnston return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
280e4656e10SMark Johnston }
281e4656e10SMark Johnston
282e4656e10SMark Johnston int
vm_inject_nmi(struct vcpu * vcpu)283e4656e10SMark Johnston vm_inject_nmi(struct vcpu *vcpu)
284e4656e10SMark Johnston {
285e4656e10SMark Johnston struct vm_nmi vmnmi;
286e4656e10SMark Johnston
287e4656e10SMark Johnston bzero(&vmnmi, sizeof(vmnmi));
288e4656e10SMark Johnston
289e4656e10SMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_NMI, &vmnmi));
290e4656e10SMark Johnston }
291e4656e10SMark Johnston
2923170dcaeSMark Johnston int
vm_inject_exception(struct vcpu * vcpu,int vector,int errcode_valid,uint32_t errcode,int restart_instruction)2933170dcaeSMark Johnston vm_inject_exception(struct vcpu *vcpu, int vector, int errcode_valid,
2943170dcaeSMark Johnston uint32_t errcode, int restart_instruction)
2953170dcaeSMark Johnston {
2963170dcaeSMark Johnston struct vm_exception exc;
2973170dcaeSMark Johnston
2983170dcaeSMark Johnston exc.vector = vector;
2993170dcaeSMark Johnston exc.error_code = errcode;
3003170dcaeSMark Johnston exc.error_code_valid = errcode_valid;
3013170dcaeSMark Johnston exc.restart_instruction = restart_instruction;
3023170dcaeSMark Johnston
3033170dcaeSMark Johnston return (vcpu_ioctl(vcpu, VM_INJECT_EXCEPTION, &exc));
3043170dcaeSMark Johnston }
3053170dcaeSMark Johnston
3063170dcaeSMark Johnston int
vm_readwrite_kernemu_device(struct vcpu * vcpu,vm_paddr_t gpa,bool write,int size,uint64_t * value)3073170dcaeSMark Johnston vm_readwrite_kernemu_device(struct vcpu *vcpu, vm_paddr_t gpa,
3083170dcaeSMark Johnston bool write, int size, uint64_t *value)
3093170dcaeSMark Johnston {
3103170dcaeSMark Johnston struct vm_readwrite_kernemu_device irp = {
3113170dcaeSMark Johnston .access_width = fls(size) - 1,
3123170dcaeSMark Johnston .gpa = gpa,
3133170dcaeSMark Johnston .value = write ? *value : ~0ul,
3143170dcaeSMark Johnston };
3153170dcaeSMark Johnston long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV);
3163170dcaeSMark Johnston int rc;
3173170dcaeSMark Johnston
3183170dcaeSMark Johnston rc = vcpu_ioctl(vcpu, cmd, &irp);
3193170dcaeSMark Johnston if (rc == 0 && !write)
3203170dcaeSMark Johnston *value = irp.value;
3213170dcaeSMark Johnston return (rc);
3223170dcaeSMark Johnston }
3233170dcaeSMark Johnston
3243170dcaeSMark Johnston int
vm_get_x2apic_state(struct vcpu * vcpu,enum x2apic_state * state)3253170dcaeSMark Johnston vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state)
3263170dcaeSMark Johnston {
3273170dcaeSMark Johnston int error;
3283170dcaeSMark Johnston struct vm_x2apic x2apic;
3293170dcaeSMark Johnston
3303170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic));
3313170dcaeSMark Johnston
3323170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_GET_X2APIC_STATE, &x2apic);
3333170dcaeSMark Johnston *state = x2apic.state;
3343170dcaeSMark Johnston return (error);
3353170dcaeSMark Johnston }
3363170dcaeSMark Johnston
3373170dcaeSMark Johnston int
vm_set_x2apic_state(struct vcpu * vcpu,enum x2apic_state state)3383170dcaeSMark Johnston vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state)
3393170dcaeSMark Johnston {
3403170dcaeSMark Johnston int error;
3413170dcaeSMark Johnston struct vm_x2apic x2apic;
3423170dcaeSMark Johnston
3433170dcaeSMark Johnston bzero(&x2apic, sizeof(x2apic));
3443170dcaeSMark Johnston x2apic.state = state;
3453170dcaeSMark Johnston
3463170dcaeSMark Johnston error = vcpu_ioctl(vcpu, VM_SET_X2APIC_STATE, &x2apic);
3473170dcaeSMark Johnston
3483170dcaeSMark Johnston return (error);
3493170dcaeSMark Johnston }
3503170dcaeSMark Johnston
3513170dcaeSMark Johnston int
vm_get_hpet_capabilities(struct vmctx * ctx,uint32_t * capabilities)3523170dcaeSMark Johnston vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
3533170dcaeSMark Johnston {
3543170dcaeSMark Johnston int error;
3553170dcaeSMark Johnston struct vm_hpet_cap cap;
3563170dcaeSMark Johnston
3573170dcaeSMark Johnston bzero(&cap, sizeof(struct vm_hpet_cap));
3583170dcaeSMark Johnston error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
3593170dcaeSMark Johnston if (capabilities != NULL)
3603170dcaeSMark Johnston *capabilities = cap.capabilities;
3613170dcaeSMark Johnston return (error);
3623170dcaeSMark Johnston }
3633170dcaeSMark Johnston
3643170dcaeSMark Johnston int
vm_rtc_write(struct vmctx * ctx,int offset,uint8_t value)3653170dcaeSMark Johnston vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
3663170dcaeSMark Johnston {
3673170dcaeSMark Johnston struct vm_rtc_data rtcdata;
3683170dcaeSMark Johnston int error;
3693170dcaeSMark Johnston
3703170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data));
3713170dcaeSMark Johnston rtcdata.offset = offset;
3723170dcaeSMark Johnston rtcdata.value = value;
3733170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
3743170dcaeSMark Johnston return (error);
3753170dcaeSMark Johnston }
3763170dcaeSMark Johnston
3773170dcaeSMark Johnston int
vm_rtc_read(struct vmctx * ctx,int offset,uint8_t * retval)3783170dcaeSMark Johnston vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
3793170dcaeSMark Johnston {
3803170dcaeSMark Johnston struct vm_rtc_data rtcdata;
3813170dcaeSMark Johnston int error;
3823170dcaeSMark Johnston
3833170dcaeSMark Johnston bzero(&rtcdata, sizeof(struct vm_rtc_data));
3843170dcaeSMark Johnston rtcdata.offset = offset;
3853170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
3863170dcaeSMark Johnston if (error == 0)
3873170dcaeSMark Johnston *retval = rtcdata.value;
3883170dcaeSMark Johnston return (error);
3893170dcaeSMark Johnston }
3903170dcaeSMark Johnston
3913170dcaeSMark Johnston int
vm_rtc_settime(struct vmctx * ctx,time_t secs)3923170dcaeSMark Johnston vm_rtc_settime(struct vmctx *ctx, time_t secs)
3933170dcaeSMark Johnston {
3943170dcaeSMark Johnston struct vm_rtc_time rtctime;
3953170dcaeSMark Johnston int error;
3963170dcaeSMark Johnston
3973170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time));
3983170dcaeSMark Johnston rtctime.secs = secs;
3993170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
4003170dcaeSMark Johnston return (error);
4013170dcaeSMark Johnston }
4023170dcaeSMark Johnston
4033170dcaeSMark Johnston int
vm_rtc_gettime(struct vmctx * ctx,time_t * secs)4043170dcaeSMark Johnston vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
4053170dcaeSMark Johnston {
4063170dcaeSMark Johnston struct vm_rtc_time rtctime;
4073170dcaeSMark Johnston int error;
4083170dcaeSMark Johnston
4093170dcaeSMark Johnston bzero(&rtctime, sizeof(struct vm_rtc_time));
4103170dcaeSMark Johnston error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
4113170dcaeSMark Johnston if (error == 0)
4123170dcaeSMark Johnston *secs = rtctime.secs;
4133170dcaeSMark Johnston return (error);
4143170dcaeSMark Johnston }
4153170dcaeSMark Johnston
416967264cfSMark Johnston /*
417967264cfSMark Johnston * From Intel Vol 3a:
418967264cfSMark Johnston * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
419967264cfSMark Johnston */
420967264cfSMark Johnston int
vcpu_reset(struct vcpu * vcpu)421967264cfSMark Johnston vcpu_reset(struct vcpu *vcpu)
422967264cfSMark Johnston {
423967264cfSMark Johnston int error;
424967264cfSMark Johnston uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
425967264cfSMark Johnston uint32_t desc_access, desc_limit;
426967264cfSMark Johnston uint16_t sel;
427967264cfSMark Johnston
428967264cfSMark Johnston zero = 0;
429967264cfSMark Johnston
430967264cfSMark Johnston rflags = 0x2;
431967264cfSMark Johnston error = vm_set_register(vcpu, VM_REG_GUEST_RFLAGS, rflags);
432967264cfSMark Johnston if (error)
433967264cfSMark Johnston goto done;
434967264cfSMark Johnston
435967264cfSMark Johnston rip = 0xfff0;
436967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RIP, rip)) != 0)
437967264cfSMark Johnston goto done;
438967264cfSMark Johnston
439967264cfSMark Johnston /*
440967264cfSMark Johnston * According to Intels Software Developer Manual CR0 should be
441967264cfSMark Johnston * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some
442967264cfSMark Johnston * guests like Windows.
443967264cfSMark Johnston */
444967264cfSMark Johnston cr0 = CR0_NE;
445967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
446967264cfSMark Johnston goto done;
447967264cfSMark Johnston
448967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR2, zero)) != 0)
449967264cfSMark Johnston goto done;
450967264cfSMark Johnston
451967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR3, zero)) != 0)
452967264cfSMark Johnston goto done;
453967264cfSMark Johnston
454967264cfSMark Johnston cr4 = 0;
455967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
456967264cfSMark Johnston goto done;
457967264cfSMark Johnston
458967264cfSMark Johnston /*
459967264cfSMark Johnston * CS: present, r/w, accessed, 16-bit, byte granularity, usable
460967264cfSMark Johnston */
461967264cfSMark Johnston desc_base = 0xffff0000;
462967264cfSMark Johnston desc_limit = 0xffff;
463967264cfSMark Johnston desc_access = 0x0093;
464967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_CS,
465967264cfSMark Johnston desc_base, desc_limit, desc_access);
466967264cfSMark Johnston if (error)
467967264cfSMark Johnston goto done;
468967264cfSMark Johnston
469967264cfSMark Johnston sel = 0xf000;
470967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_CS, sel)) != 0)
471967264cfSMark Johnston goto done;
472967264cfSMark Johnston
473967264cfSMark Johnston /*
474967264cfSMark Johnston * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
475967264cfSMark Johnston */
476967264cfSMark Johnston desc_base = 0;
477967264cfSMark Johnston desc_limit = 0xffff;
478967264cfSMark Johnston desc_access = 0x0093;
479967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_SS,
480967264cfSMark Johnston desc_base, desc_limit, desc_access);
481967264cfSMark Johnston if (error)
482967264cfSMark Johnston goto done;
483967264cfSMark Johnston
484967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_DS,
485967264cfSMark Johnston desc_base, desc_limit, desc_access);
486967264cfSMark Johnston if (error)
487967264cfSMark Johnston goto done;
488967264cfSMark Johnston
489967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_ES,
490967264cfSMark Johnston desc_base, desc_limit, desc_access);
491967264cfSMark Johnston if (error)
492967264cfSMark Johnston goto done;
493967264cfSMark Johnston
494967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_FS,
495967264cfSMark Johnston desc_base, desc_limit, desc_access);
496967264cfSMark Johnston if (error)
497967264cfSMark Johnston goto done;
498967264cfSMark Johnston
499967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GS,
500967264cfSMark Johnston desc_base, desc_limit, desc_access);
501967264cfSMark Johnston if (error)
502967264cfSMark Johnston goto done;
503967264cfSMark Johnston
504967264cfSMark Johnston sel = 0;
505967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_SS, sel)) != 0)
506967264cfSMark Johnston goto done;
507967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DS, sel)) != 0)
508967264cfSMark Johnston goto done;
509967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_ES, sel)) != 0)
510967264cfSMark Johnston goto done;
511967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_FS, sel)) != 0)
512967264cfSMark Johnston goto done;
513967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_GS, sel)) != 0)
514967264cfSMark Johnston goto done;
515967264cfSMark Johnston
516967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_EFER, zero)) != 0)
517967264cfSMark Johnston goto done;
518967264cfSMark Johnston
519967264cfSMark Johnston /* General purpose registers */
520967264cfSMark Johnston rdx = 0xf00;
521967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RAX, zero)) != 0)
522967264cfSMark Johnston goto done;
523967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBX, zero)) != 0)
524967264cfSMark Johnston goto done;
525967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RCX, zero)) != 0)
526967264cfSMark Johnston goto done;
527967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
528967264cfSMark Johnston goto done;
529967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSI, zero)) != 0)
530967264cfSMark Johnston goto done;
531967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDI, zero)) != 0)
532967264cfSMark Johnston goto done;
533967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBP, zero)) != 0)
534967264cfSMark Johnston goto done;
535967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSP, zero)) != 0)
536967264cfSMark Johnston goto done;
537967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R8, zero)) != 0)
538967264cfSMark Johnston goto done;
539967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R9, zero)) != 0)
540967264cfSMark Johnston goto done;
541967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R10, zero)) != 0)
542967264cfSMark Johnston goto done;
543967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R11, zero)) != 0)
544967264cfSMark Johnston goto done;
545967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R12, zero)) != 0)
546967264cfSMark Johnston goto done;
547967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R13, zero)) != 0)
548967264cfSMark Johnston goto done;
549967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R14, zero)) != 0)
550967264cfSMark Johnston goto done;
551967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_R15, zero)) != 0)
552967264cfSMark Johnston goto done;
553967264cfSMark Johnston
554967264cfSMark Johnston /* GDTR, IDTR */
555967264cfSMark Johnston desc_base = 0;
556967264cfSMark Johnston desc_limit = 0xffff;
557967264cfSMark Johnston desc_access = 0;
558967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_GDTR,
559967264cfSMark Johnston desc_base, desc_limit, desc_access);
560967264cfSMark Johnston if (error != 0)
561967264cfSMark Johnston goto done;
562967264cfSMark Johnston
563967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_IDTR,
564967264cfSMark Johnston desc_base, desc_limit, desc_access);
565967264cfSMark Johnston if (error != 0)
566967264cfSMark Johnston goto done;
567967264cfSMark Johnston
568967264cfSMark Johnston /* TR */
569967264cfSMark Johnston desc_base = 0;
570967264cfSMark Johnston desc_limit = 0xffff;
571967264cfSMark Johnston desc_access = 0x0000008b;
572967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
573967264cfSMark Johnston if (error)
574967264cfSMark Johnston goto done;
575967264cfSMark Johnston
576967264cfSMark Johnston sel = 0;
577967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_TR, sel)) != 0)
578967264cfSMark Johnston goto done;
579967264cfSMark Johnston
580967264cfSMark Johnston /* LDTR */
581967264cfSMark Johnston desc_base = 0;
582967264cfSMark Johnston desc_limit = 0xffff;
583967264cfSMark Johnston desc_access = 0x00000082;
584967264cfSMark Johnston error = vm_set_desc(vcpu, VM_REG_GUEST_LDTR, desc_base,
585967264cfSMark Johnston desc_limit, desc_access);
586967264cfSMark Johnston if (error)
587967264cfSMark Johnston goto done;
588967264cfSMark Johnston
589967264cfSMark Johnston sel = 0;
590967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
591967264cfSMark Johnston goto done;
592967264cfSMark Johnston
593967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR6,
594967264cfSMark Johnston 0xffff0ff0)) != 0)
595967264cfSMark Johnston goto done;
596967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR7, 0x400)) !=
597967264cfSMark Johnston 0)
598967264cfSMark Johnston goto done;
599967264cfSMark Johnston
600967264cfSMark Johnston if ((error = vm_set_register(vcpu, VM_REG_GUEST_INTR_SHADOW,
601967264cfSMark Johnston zero)) != 0)
602967264cfSMark Johnston goto done;
603967264cfSMark Johnston
604967264cfSMark Johnston error = 0;
605967264cfSMark Johnston done:
606967264cfSMark Johnston return (error);
607967264cfSMark Johnston }
608