2 * Copyright (c) 2011 NetApp, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/types.h>
34 #include <machine/specialreg.h>
35 #include <machine/segments.h>
36 #include <machine/vmm.h>
40 #define DESC_UNUSABLE 0x00010000
42 #define GUEST_NULL_SEL 0
43 #define GUEST_CODE_SEL 1
44 #define GUEST_DATA_SEL 2
45 #define GUEST_GDTR_LIMIT (3 * 8 - 1)
48 vm_setup_freebsd_gdt(uint64_t *gdtr)
50 gdtr[GUEST_NULL_SEL] = 0;
51 gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
52 gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
56 * Setup the 'vcpu' register set such that it will begin execution at
60 vm_setup_freebsd_registers(struct vmctx *vmctx, int vcpu,
61 uint64_t rip, uint64_t cr3, uint64_t gdtbase,
65 uint64_t cr0, cr4, efer, rflags, desc_base;
66 uint32_t desc_access, desc_limit;
69 cr0 = CR0_PE | CR0_PG | CR0_NE;
70 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
74 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
77 efer = EFER_LME | EFER_LMA;
78 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, efer)))
82 error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
88 desc_access = 0x0000209B;
89 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
90 desc_base, desc_limit, desc_access);
94 desc_access = 0x00000093;
95 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
96 desc_base, desc_limit, desc_access);
100 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
101 desc_base, desc_limit, desc_access);
105 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
106 desc_base, desc_limit, desc_access);
110 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
111 desc_base, desc_limit, desc_access);
115 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
116 desc_base, desc_limit, desc_access);
121 * XXX TR is pointing to null selector even though we set the
122 * TSS segment to be usable with a base address and limit of 0.
124 desc_access = 0x0000008b;
125 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
129 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, 0, 0,
134 gsel = GSEL(GUEST_CODE_SEL, SEL_KPL);
135 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, gsel)) != 0)
138 gsel = GSEL(GUEST_DATA_SEL, SEL_KPL);
139 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, gsel)) != 0)
142 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, gsel)) != 0)
145 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, gsel)) != 0)
148 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, gsel)) != 0)
151 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, gsel)) != 0)
154 /* XXX TR is pointing to the null selector */
155 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, 0)) != 0)
158 /* LDTR is pointing to the null selector */
159 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
163 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
166 /* page table base */
167 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, cr3)) != 0)
171 desc_limit = GUEST_GDTR_LIMIT;
172 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
173 desc_base, desc_limit, 0);
177 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, rsp)) != 0)