]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libvmmapi/vmmapi_freebsd.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / lib / libvmmapi / vmmapi_freebsd.c
1 /*-
2  * Copyright (c) 2011 NetApp, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33
34 #include <machine/specialreg.h>
35 #include <machine/segments.h>
36 #include <machine/vmm.h>
37
38 #include "vmmapi.h"
39
40 #define DESC_UNUSABLE           0x00010000
41
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)
46
47 void     
48 vm_setup_freebsd_gdt(uint64_t *gdtr)
49 {       
50         gdtr[GUEST_NULL_SEL] = 0;
51         gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
52         gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
53 }
54
55 /*
56  * Setup the 'vcpu' register set such that it will begin execution at
57  * 'rip' in long mode.
58  */
59 int
60 vm_setup_freebsd_registers(struct vmctx *vmctx, int vcpu,
61                            uint64_t rip, uint64_t cr3, uint64_t gdtbase,
62                            uint64_t rsp)
63 {
64         int error;
65         uint64_t cr0, cr4, efer, rflags, desc_base;
66         uint32_t desc_access, desc_limit;
67         uint16_t gsel;
68
69         cr0 = CR0_PE | CR0_PG | CR0_NE;
70         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
71                 goto done;
72
73         cr4 = CR4_PAE;
74         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
75                 goto done;
76
77         efer = EFER_LME | EFER_LMA;
78         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, efer)))
79                 goto done;
80
81         rflags = 0x2;
82         error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
83         if (error)
84                 goto done;
85
86         desc_base = 0;
87         desc_limit = 0;
88         desc_access = 0x0000209B;
89         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
90                             desc_base, desc_limit, desc_access);
91         if (error)
92                 goto done;
93
94         desc_access = 0x00000093;
95         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
96                             desc_base, desc_limit, desc_access);
97         if (error)
98                 goto done;
99
100         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
101                             desc_base, desc_limit, desc_access);
102         if (error)
103                 goto done;
104
105         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
106                             desc_base, desc_limit, desc_access);
107         if (error)
108                 goto done;
109
110         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
111                             desc_base, desc_limit, desc_access);
112         if (error)
113                 goto done;
114
115         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
116                             desc_base, desc_limit, desc_access);
117         if (error)
118                 goto done;
119
120         /*
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.
123          */
124         desc_access = 0x0000008b;
125         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
126         if (error)
127                 goto done;
128
129         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, 0, 0,
130                             DESC_UNUSABLE);
131         if (error)
132                 goto done;
133
134         gsel = GSEL(GUEST_CODE_SEL, SEL_KPL);
135         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, gsel)) != 0)
136                 goto done;
137         
138         gsel = GSEL(GUEST_DATA_SEL, SEL_KPL);
139         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, gsel)) != 0)
140                 goto done;
141         
142         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, gsel)) != 0)
143                 goto done;
144
145         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, gsel)) != 0)
146                 goto done;
147         
148         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, gsel)) != 0)
149                 goto done;
150         
151         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, gsel)) != 0)
152                 goto done;
153
154         /* XXX TR is pointing to the null selector */
155         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, 0)) != 0)
156                 goto done;
157
158         /* LDTR is pointing to the null selector */
159         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
160                 goto done;
161
162         /* entry point */
163         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
164                 goto done;
165
166         /* page table base */
167         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, cr3)) != 0)
168                 goto done;
169
170         desc_base = gdtbase;
171         desc_limit = GUEST_GDTR_LIMIT;
172         error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
173                             desc_base, desc_limit, 0);
174         if (error != 0)
175                 goto done;
176
177         if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, rsp)) != 0)
178                 goto done;
179
180         error = 0;
181 done:
182         return (error);
183 }