xref: /freebsd/lib/libvmmapi/amd64/vmmapi_machdep.c (revision 3170dcaea96debdd383d974f2b1582d2eb126f50)
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