vmmapi.c revision 239025
172339Sabial/*-
272339Sabial * Copyright (c) 2011 NetApp, Inc.
372339Sabial * All rights reserved.
472339Sabial *
572339Sabial * Redistribution and use in source and binary forms, with or without
672339Sabial * modification, are permitted provided that the following conditions
772339Sabial * are met:
872339Sabial * 1. Redistributions of source code must retain the above copyright
972339Sabial *    notice, this list of conditions and the following disclaimer.
1072339Sabial * 2. Redistributions in binary form must reproduce the above copyright
1172339Sabial *    notice, this list of conditions and the following disclaimer in the
1272339Sabial *    documentation and/or other materials provided with the distribution.
1372339Sabial *
1472339Sabial * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
1572339Sabial * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1672339Sabial * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1772339Sabial * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
1872339Sabial * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1972339Sabial * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2072339Sabial * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2172339Sabial * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2272339Sabial * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2372339Sabial * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2472339Sabial * SUCH DAMAGE.
2572339Sabial *
2672339Sabial * $FreeBSD$
2772339Sabial */
2872339Sabial
2972339Sabial#include <sys/cdefs.h>
3072339Sabial__FBSDID("$FreeBSD$");
3172339Sabial
3272339Sabial#include <sys/types.h>
3372339Sabial#include <sys/sysctl.h>
3472339Sabial#include <sys/ioctl.h>
3572339Sabial#include <sys/mman.h>
3672339Sabial
3772339Sabial#include <machine/specialreg.h>
3872339Sabial
3972339Sabial#include <stdio.h>
4072339Sabial#include <stdlib.h>
4172339Sabial#include <assert.h>
4272339Sabial#include <string.h>
4372339Sabial#include <fcntl.h>
4472339Sabial#include <unistd.h>
4572339Sabial
4672339Sabial#include <machine/vmm.h>
4772339Sabial#include <machine/vmm_dev.h>
4872339Sabial
4972339Sabial#include "vmmapi.h"
5072339Sabial#include "mptable.h"
5172339Sabial
5272339Sabial#define BIOS_ROM_BASE		(0xf0000)
5372339Sabial#define BIOS_ROM_SIZE		(0x10000)
5472339Sabial
5572339Sabialstruct vmctx {
5672339Sabial	int	fd;
5772339Sabial	char	*name;
5872339Sabial};
5972339Sabial
6072339Sabial#define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
6172339Sabial#define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
6272339Sabial
6372339Sabialstatic int
6472339Sabialvm_device_open(const char *name)
6572339Sabial{
6672339Sabial        int fd, len;
6772339Sabial        char *vmfile;
6872339Sabial
6972339Sabial	len = strlen("/dev/vmm/") + strlen(name) + 1;
7072339Sabial	vmfile = malloc(len);
7172339Sabial	assert(vmfile != NULL);
7272339Sabial	snprintf(vmfile, len, "/dev/vmm/%s", name);
7372339Sabial
7472339Sabial        /* Open the device file */
7572339Sabial        fd = open(vmfile, O_RDWR, 0);
7672339Sabial
7772339Sabial	free(vmfile);
7872339Sabial        return (fd);
7972339Sabial}
8072339Sabial
8172339Sabialint
8272339Sabialvm_create(const char *name)
8372339Sabial{
8472339Sabial
8572339Sabial	return (CREATE((char *)name));
8672339Sabial}
8772339Sabial
8872339Sabialstruct vmctx *
8972339Sabialvm_open(const char *name)
9072339Sabial{
9172339Sabial	struct vmctx *vm;
9272339Sabial
9372339Sabial	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
9472339Sabial	assert(vm != NULL);
9572339Sabial
9672339Sabial	vm->fd = -1;
9772339Sabial	vm->name = (char *)(vm + 1);
9872339Sabial	strcpy(vm->name, name);
9972339Sabial
10072339Sabial	if ((vm->fd = vm_device_open(vm->name)) < 0)
10172339Sabial		goto err;
10272339Sabial
10372339Sabial	return (vm);
10472339Sabialerr:
10572339Sabial	vm_destroy(vm);
10672339Sabial	return (NULL);
10772339Sabial}
10872339Sabial
10972339Sabialvoid
11072339Sabialvm_destroy(struct vmctx *vm)
11172339Sabial{
11272339Sabial	assert(vm != NULL);
11372339Sabial
11472339Sabial	DESTROY(vm->name);
11572339Sabial	if (vm->fd >= 0)
11672339Sabial		close(vm->fd);
11772339Sabial	free(vm);
11872339Sabial}
11972339Sabial
12072339Sabialint
12172339Sabialvm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa,
12272339Sabial		  vm_paddr_t *ret_hpa, size_t *ret_len)
12372339Sabial{
12472339Sabial	int error;
12572339Sabial	struct vm_memory_segment seg;
12672339Sabial
12772339Sabial	bzero(&seg, sizeof(seg));
12872339Sabial	seg.gpa = gpa;
12972339Sabial	error = ioctl(ctx->fd, VM_GET_MEMORY_SEG, &seg);
13072339Sabial	*ret_hpa = seg.hpa;
13172339Sabial	*ret_len = seg.len;
13272339Sabial	return (error);
13372339Sabial}
13472339Sabial
13572339Sabialint
13672339Sabialvm_setup_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char **mapaddr)
13772339Sabial{
13872339Sabial	int error;
13972339Sabial	struct vm_memory_segment seg;
14072339Sabial
14172339Sabial	/*
14272339Sabial	 * Create and optionally map 'len' bytes of memory at guest
14372339Sabial	 * physical address 'gpa'
14472339Sabial	 */
14572339Sabial	bzero(&seg, sizeof(seg));
14672339Sabial	seg.gpa = gpa;
14772339Sabial	seg.len = len;
14872339Sabial	error = ioctl(ctx->fd, VM_MAP_MEMORY, &seg);
14972339Sabial	if (error == 0 && mapaddr != NULL) {
15072339Sabial		*mapaddr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
15172339Sabial				ctx->fd, gpa);
15272339Sabial	}
15372339Sabial	return (error);
15472339Sabial}
15572339Sabial
15672339Sabialchar *
15772339Sabialvm_map_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
15872339Sabial{
15972339Sabial
16072339Sabial	/* Map 'len' bytes of memory at guest physical address 'gpa' */
16172339Sabial	return ((char *)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
16272339Sabial		     ctx->fd, gpa));
16372339Sabial}
16472339Sabial
16572339Sabialint
16672339Sabialvm_set_desc(struct vmctx *ctx, int vcpu, int reg,
16772339Sabial	    uint64_t base, uint32_t limit, uint32_t access)
16872339Sabial{
16972339Sabial	int error;
17072339Sabial	struct vm_seg_desc vmsegdesc;
17172339Sabial
17272339Sabial	bzero(&vmsegdesc, sizeof(vmsegdesc));
17372339Sabial	vmsegdesc.cpuid = vcpu;
17472339Sabial	vmsegdesc.regnum = reg;
17572339Sabial	vmsegdesc.desc.base = base;
17672339Sabial	vmsegdesc.desc.limit = limit;
17772339Sabial	vmsegdesc.desc.access = access;
17872339Sabial
17972339Sabial	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
18072339Sabial	return (error);
18172339Sabial}
18272339Sabial
18372339Sabialint
18472339Sabialvm_get_desc(struct vmctx *ctx, int vcpu, int reg,
18572339Sabial	    uint64_t *base, uint32_t *limit, uint32_t *access)
18672339Sabial{
18772339Sabial	int error;
18872339Sabial	struct vm_seg_desc vmsegdesc;
18972339Sabial
19072339Sabial	bzero(&vmsegdesc, sizeof(vmsegdesc));
19172339Sabial	vmsegdesc.cpuid = vcpu;
19272339Sabial	vmsegdesc.regnum = reg;
19372339Sabial
19472339Sabial	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
19572339Sabial	if (error == 0) {
19672339Sabial		*base = vmsegdesc.desc.base;
19772339Sabial		*limit = vmsegdesc.desc.limit;
19872339Sabial		*access = vmsegdesc.desc.access;
19972339Sabial	}
20072339Sabial	return (error);
20172339Sabial}
20272339Sabial
20372339Sabialint
20472339Sabialvm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
20572339Sabial{
20672339Sabial	int error;
20772339Sabial	struct vm_register vmreg;
20872339Sabial
20972339Sabial	bzero(&vmreg, sizeof(vmreg));
21072339Sabial	vmreg.cpuid = vcpu;
21172339Sabial	vmreg.regnum = reg;
21272339Sabial	vmreg.regval = val;
21372339Sabial
21472339Sabial	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
21572339Sabial	return (error);
21672339Sabial}
21772339Sabial
21872339Sabialint
21972339Sabialvm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
22072339Sabial{
22172339Sabial	int error;
22272339Sabial	struct vm_register vmreg;
22372339Sabial
22472339Sabial	bzero(&vmreg, sizeof(vmreg));
22572339Sabial	vmreg.cpuid = vcpu;
22672339Sabial	vmreg.regnum = reg;
22772339Sabial
22872339Sabial	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
22972339Sabial	*ret_val = vmreg.regval;
23072339Sabial	return (error);
23172339Sabial}
23272339Sabial
23372339Sabialint
23472339Sabialvm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid)
23572339Sabial{
23672339Sabial	int error;
23772339Sabial	struct vm_pin vmpin;
23872339Sabial
23972339Sabial	bzero(&vmpin, sizeof(vmpin));
24072339Sabial	vmpin.vm_cpuid = vcpu;
24172339Sabial
24272339Sabial	error = ioctl(ctx->fd, VM_GET_PINNING, &vmpin);
24372339Sabial	*host_cpuid = vmpin.host_cpuid;
24472339Sabial	return (error);
24572339Sabial}
24672339Sabial
24772339Sabialint
24872339Sabialvm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid)
24972339Sabial{
25072339Sabial	int error;
25172339Sabial	struct vm_pin vmpin;
25272339Sabial
25372339Sabial	bzero(&vmpin, sizeof(vmpin));
25472339Sabial	vmpin.vm_cpuid = vcpu;
25572339Sabial	vmpin.host_cpuid = host_cpuid;
25672339Sabial
25772339Sabial	error = ioctl(ctx->fd, VM_SET_PINNING, &vmpin);
25872339Sabial	return (error);
25972339Sabial}
26072339Sabial
26172339Sabialint
26272339Sabialvm_run(struct vmctx *ctx, int vcpu, uint64_t rip, struct vm_exit *vmexit)
26372339Sabial{
26472339Sabial	int error;
26572339Sabial	struct vm_run vmrun;
26672339Sabial
26772339Sabial	bzero(&vmrun, sizeof(vmrun));
26872339Sabial	vmrun.cpuid = vcpu;
26972339Sabial	vmrun.rip = rip;
27072339Sabial
27172339Sabial	error = ioctl(ctx->fd, VM_RUN, &vmrun);
27272339Sabial	bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
27372339Sabial	return (error);
27472339Sabial}
27572339Sabial
27672339Sabialstatic int
27772339Sabialvm_inject_event_real(struct vmctx *ctx, int vcpu, enum vm_event_type type,
27872339Sabial		     int vector, int error_code, int error_code_valid)
27972339Sabial{
28072339Sabial	struct vm_event ev;
28172339Sabial
28272339Sabial	bzero(&ev, sizeof(ev));
28372339Sabial	ev.cpuid = vcpu;
28472339Sabial	ev.type = type;
28572339Sabial	ev.vector = vector;
28672339Sabial	ev.error_code = error_code;
28772339Sabial	ev.error_code_valid = error_code_valid;
28872339Sabial
28972339Sabial	return (ioctl(ctx->fd, VM_INJECT_EVENT, &ev));
29072339Sabial}
29172339Sabial
29272339Sabialint
29372339Sabialvm_inject_event(struct vmctx *ctx, int vcpu, enum vm_event_type type,
29472339Sabial		int vector)
29572339Sabial{
29672339Sabial
29772339Sabial	return (vm_inject_event_real(ctx, vcpu, type, vector, 0, 0));
29872339Sabial}
29972339Sabial
30072339Sabialint
30172339Sabialvm_inject_event2(struct vmctx *ctx, int vcpu, enum vm_event_type type,
30272339Sabial		 int vector, int error_code)
30372339Sabial{
30472339Sabial
30572339Sabial	return (vm_inject_event_real(ctx, vcpu, type, vector, error_code, 1));
30672339Sabial}
30772339Sabial
30872339Sabialint
30972339Sabialvm_build_tables(struct vmctx *ctxt, int ncpu, void *oemtbl, int oemtblsz)
31072339Sabial{
31172339Sabial
31272339Sabial	return (vm_build_mptable(ctxt, BIOS_ROM_BASE, BIOS_ROM_SIZE, ncpu,
31372339Sabial				 oemtbl, oemtblsz));
31472339Sabial}
31572339Sabial
31672339Sabialint
31772339Sabialvm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
31872339Sabial{
31972339Sabial	struct vm_lapic_irq vmirq;
32072339Sabial
32172339Sabial	bzero(&vmirq, sizeof(vmirq));
32272339Sabial	vmirq.cpuid = vcpu;
32372339Sabial	vmirq.vector = vector;
32472339Sabial
32572339Sabial	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
32672339Sabial}
32772339Sabial
32872339Sabialint
32972339Sabialvm_inject_nmi(struct vmctx *ctx, int vcpu)
33072339Sabial{
33172339Sabial	struct vm_nmi vmnmi;
33272339Sabial
33372339Sabial	bzero(&vmnmi, sizeof(vmnmi));
33472339Sabial	vmnmi.cpuid = vcpu;
33572339Sabial
33672339Sabial	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
33772339Sabial}
33872339Sabial
33972339Sabialint
34072339Sabialvm_capability_name2type(const char *capname)
34172339Sabial{
34272339Sabial	int i;
34372339Sabial
34472339Sabial	static struct {
34572339Sabial		const char	*name;
34672339Sabial		int		type;
34772339Sabial	} capstrmap[] = {
34872339Sabial		{ "hlt_exit",		VM_CAP_HALT_EXIT },
34972339Sabial		{ "mtrap_exit",		VM_CAP_MTRAP_EXIT },
35072339Sabial		{ "pause_exit",		VM_CAP_PAUSE_EXIT },
35172339Sabial		{ "unrestricted_guest",	VM_CAP_UNRESTRICTED_GUEST },
35272339Sabial		{ 0 }
35372339Sabial	};
35472339Sabial
35572339Sabial	for (i = 0; capstrmap[i].name != NULL && capname != NULL; i++) {
35672339Sabial		if (strcmp(capstrmap[i].name, capname) == 0)
35772339Sabial			return (capstrmap[i].type);
35872339Sabial	}
35972339Sabial
36072339Sabial	return (-1);
36172339Sabial}
36272339Sabial
36372339Sabialint
36472339Sabialvm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
36572339Sabial		  int *retval)
36672339Sabial{
36772339Sabial	int error;
36872339Sabial	struct vm_capability vmcap;
36972339Sabial
37072339Sabial	bzero(&vmcap, sizeof(vmcap));
37172339Sabial	vmcap.cpuid = vcpu;
37272339Sabial	vmcap.captype = cap;
37372339Sabial
37472339Sabial	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
37572339Sabial	*retval = vmcap.capval;
37672339Sabial	return (error);
37772339Sabial}
37872339Sabial
37972339Sabialint
38072339Sabialvm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
38172339Sabial{
38272339Sabial	struct vm_capability vmcap;
38372339Sabial
38472339Sabial	bzero(&vmcap, sizeof(vmcap));
38572339Sabial	vmcap.cpuid = vcpu;
38672339Sabial	vmcap.captype = cap;
38772339Sabial	vmcap.capval = val;
38872339Sabial
38972339Sabial	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
39072339Sabial}
39172339Sabial
39272339Sabialint
39372339Sabialvm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
39472339Sabial{
39572339Sabial	struct vm_pptdev pptdev;
39672339Sabial
39772339Sabial	bzero(&pptdev, sizeof(pptdev));
39872339Sabial	pptdev.bus = bus;
39972339Sabial	pptdev.slot = slot;
40072339Sabial	pptdev.func = func;
40172339Sabial
40272339Sabial	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
40372339Sabial}
40472339Sabial
40572339Sabialint
40672339Sabialvm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
40772339Sabial{
40872339Sabial	struct vm_pptdev pptdev;
40972339Sabial
41072339Sabial	bzero(&pptdev, sizeof(pptdev));
41172339Sabial	pptdev.bus = bus;
41272339Sabial	pptdev.slot = slot;
41372339Sabial	pptdev.func = func;
41472339Sabial
41572339Sabial	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
41672339Sabial}
41772339Sabial
41872339Sabialint
41972339Sabialvm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
42072339Sabial		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
42172339Sabial{
42272339Sabial	struct vm_pptdev_mmio pptmmio;
42372339Sabial
42472339Sabial	bzero(&pptmmio, sizeof(pptmmio));
42572339Sabial	pptmmio.bus = bus;
42672339Sabial	pptmmio.slot = slot;
42772339Sabial	pptmmio.func = func;
42872339Sabial	pptmmio.gpa = gpa;
42972339Sabial	pptmmio.len = len;
43072339Sabial	pptmmio.hpa = hpa;
43172339Sabial
43272339Sabial	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
43372339Sabial}
43472339Sabial
43572339Sabialint
43672339Sabialvm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
43772339Sabial	     int destcpu, int vector, int numvec)
43872339Sabial{
43972339Sabial	struct vm_pptdev_msi pptmsi;
44072339Sabial
44172339Sabial	bzero(&pptmsi, sizeof(pptmsi));
44272339Sabial	pptmsi.vcpu = vcpu;
44372339Sabial	pptmsi.bus = bus;
44472339Sabial	pptmsi.slot = slot;
44572339Sabial	pptmsi.func = func;
44672339Sabial	pptmsi.destcpu = destcpu;
44772339Sabial	pptmsi.vector = vector;
44872339Sabial	pptmsi.numvec = numvec;
44972339Sabial
45072339Sabial	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
45172339Sabial}
45272339Sabial
45372339Sabialint
45472339Sabialvm_setup_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
45572339Sabial	      int idx, uint32_t msg, uint32_t vector_control, uint64_t addr)
45672339Sabial{
45772339Sabial	struct vm_pptdev_msix pptmsix;
45872339Sabial
45972339Sabial	bzero(&pptmsix, sizeof(pptmsix));
46072339Sabial	pptmsix.vcpu = vcpu;
46172339Sabial	pptmsix.bus = bus;
46272339Sabial	pptmsix.slot = slot;
46372339Sabial	pptmsix.func = func;
46472339Sabial	pptmsix.idx = idx;
46572339Sabial	pptmsix.msg = msg;
46672339Sabial	pptmsix.addr = addr;
46772339Sabial	pptmsix.vector_control = vector_control;
46872339Sabial
46972339Sabial	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
47072339Sabial}
47172339Sabial
47272339Sabialuint64_t *
47372339Sabialvm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
47472339Sabial	     int *ret_entries)
47572339Sabial{
47672339Sabial	int error;
47772339Sabial
47872339Sabial	static struct vm_stats vmstats;
47972339Sabial
48072339Sabial	vmstats.cpuid = vcpu;
48172339Sabial
48272339Sabial	error = ioctl(ctx->fd, VM_STATS, &vmstats);
48372339Sabial	if (error == 0) {
48472339Sabial		if (ret_entries)
48572339Sabial			*ret_entries = vmstats.num_entries;
48672339Sabial		if (ret_tv)
48772339Sabial			*ret_tv = vmstats.tv;
48872339Sabial		return (vmstats.statbuf);
48972339Sabial	} else
49072339Sabial		return (NULL);
49172339Sabial}
49272339Sabial
49372339Sabialconst char *
49472339Sabialvm_get_stat_desc(struct vmctx *ctx, int index)
49572339Sabial{
49672339Sabial	static struct vm_stat_desc statdesc;
49772339Sabial
49872339Sabial	statdesc.index = index;
49972339Sabial	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
50072339Sabial		return (statdesc.desc);
50172339Sabial	else
50272339Sabial		return (NULL);
50372339Sabial}
50472339Sabial
50572339Sabial/*
50672339Sabial * From Intel Vol 3a:
50772339Sabial * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
50872339Sabial */
50972339Sabialint
51072339Sabialvcpu_reset(struct vmctx *vmctx, int vcpu)
51172339Sabial{
51272339Sabial	int error;
51372339Sabial	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
51472339Sabial	uint32_t desc_access, desc_limit;
51572339Sabial	uint16_t sel;
51672339Sabial
51772339Sabial	zero = 0;
51872339Sabial
51972339Sabial	rflags = 0x2;
52072339Sabial	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
52172339Sabial	if (error)
52272339Sabial		goto done;
52372339Sabial
52472339Sabial	rip = 0xfff0;
52572339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
52672339Sabial		goto done;
52772339Sabial
52872339Sabial	cr0 = CR0_NE;
52972339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
53072339Sabial		goto done;
53172339Sabial
53272339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
53372339Sabial		goto done;
53472339Sabial
53572339Sabial	cr4 = 0;
53672339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
53772339Sabial		goto done;
53872339Sabial
53972339Sabial	/*
54072339Sabial	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
54172339Sabial	 */
54272339Sabial	desc_base = 0xffff0000;
54372339Sabial	desc_limit = 0xffff;
54472339Sabial	desc_access = 0x0093;
54572339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
54672339Sabial			    desc_base, desc_limit, desc_access);
54772339Sabial	if (error)
54872339Sabial		goto done;
54972339Sabial
55072339Sabial	sel = 0xf000;
55172339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
55272339Sabial		goto done;
55372339Sabial
55472339Sabial	/*
55572339Sabial	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
55672339Sabial	 */
55772339Sabial	desc_base = 0;
55872339Sabial	desc_limit = 0xffff;
55972339Sabial	desc_access = 0x0093;
56072339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
56172339Sabial			    desc_base, desc_limit, desc_access);
56272339Sabial	if (error)
56372339Sabial		goto done;
56472339Sabial
56572339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
56672339Sabial			    desc_base, desc_limit, desc_access);
56772339Sabial	if (error)
56872339Sabial		goto done;
56972339Sabial
57072339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
57172339Sabial			    desc_base, desc_limit, desc_access);
57272339Sabial	if (error)
57372339Sabial		goto done;
57472339Sabial
57572339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
57672339Sabial			    desc_base, desc_limit, desc_access);
57772339Sabial	if (error)
57872339Sabial		goto done;
57972339Sabial
58072339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
58172339Sabial			    desc_base, desc_limit, desc_access);
58272339Sabial	if (error)
58372339Sabial		goto done;
58472339Sabial
58572339Sabial	sel = 0;
58672339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
58772339Sabial		goto done;
58872339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
58972339Sabial		goto done;
59072339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
59172339Sabial		goto done;
59272339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
59372339Sabial		goto done;
59472339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
59572339Sabial		goto done;
59672339Sabial
59772339Sabial	/* General purpose registers */
59872339Sabial	rdx = 0xf00;
59972339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
60072339Sabial		goto done;
60172339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
60272339Sabial		goto done;
60372339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
60472339Sabial		goto done;
60572339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
60672339Sabial		goto done;
60772339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
60872339Sabial		goto done;
60972339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
61072339Sabial		goto done;
61172339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
61272339Sabial		goto done;
61372339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
61472339Sabial		goto done;
61572339Sabial
61672339Sabial	/* GDTR, IDTR */
61772339Sabial	desc_base = 0;
61872339Sabial	desc_limit = 0xffff;
61972339Sabial	desc_access = 0;
62072339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
62172339Sabial			    desc_base, desc_limit, desc_access);
62272339Sabial	if (error != 0)
62372339Sabial		goto done;
62472339Sabial
62572339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
62672339Sabial			    desc_base, desc_limit, desc_access);
62772339Sabial	if (error != 0)
62872339Sabial		goto done;
62972339Sabial
63072339Sabial	/* TR */
63172339Sabial	desc_base = 0;
63272339Sabial	desc_limit = 0xffff;
63372339Sabial	desc_access = 0x0000008b;
63472339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
63572339Sabial	if (error)
63672339Sabial		goto done;
63772339Sabial
63872339Sabial	sel = 0;
63972339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
64072339Sabial		goto done;
64172339Sabial
64272339Sabial	/* LDTR */
64372339Sabial	desc_base = 0;
64472339Sabial	desc_limit = 0xffff;
64572339Sabial	desc_access = 0x00000082;
64672339Sabial	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
64772339Sabial			    desc_limit, desc_access);
64872339Sabial	if (error)
64972339Sabial		goto done;
65072339Sabial
65172339Sabial	sel = 0;
65272339Sabial	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
65372339Sabial		goto done;
65472339Sabial
65572339Sabial	/* XXX cr2, debug registers */
65672339Sabial
65772339Sabial	error = 0;
65872339Sabialdone:
65972339Sabial	return (error);
66072339Sabial}
66172339Sabial