]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/amd64/vmm/x86.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / amd64 / vmm / x86.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/param.h>
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/cpuset.h>
36
37 #include <machine/clock.h>
38 #include <machine/cpufunc.h>
39 #include <machine/md_var.h>
40 #include <machine/specialreg.h>
41
42 #include <machine/vmm.h>
43
44 #include "x86.h"
45
46 #define CPUID_VM_HIGH           0x40000000
47
48 static const char bhyve_id[12] = "bhyve bhyve ";
49
50 static uint64_t bhyve_xcpuids;
51
52 int
53 x86_emulate_cpuid(struct vm *vm, int vcpu_id,
54                   uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
55 {
56         int error, enable_invpcid;
57         unsigned int    func, regs[4];
58         enum x2apic_state x2apic_state;
59
60         /*
61          * Requests for invalid CPUID levels should map to the highest
62          * available level instead.
63          */
64         if (cpu_exthigh != 0 && *eax >= 0x80000000) {
65                 if (*eax > cpu_exthigh)
66                         *eax = cpu_exthigh;
67         } else if (*eax >= 0x40000000) {
68                 if (*eax > CPUID_VM_HIGH)
69                         *eax = CPUID_VM_HIGH;
70         } else if (*eax > cpu_high) {
71                 *eax = cpu_high;
72         }
73
74         func = *eax;
75
76         /*
77          * In general the approach used for CPU topology is to
78          * advertise a flat topology where all CPUs are packages with
79          * no multi-core or SMT.
80          */
81         switch (func) {
82                 /*
83                  * Pass these through to the guest
84                  */
85                 case CPUID_0000_0000:
86                 case CPUID_0000_0002:
87                 case CPUID_0000_0003:
88                 case CPUID_8000_0000:
89                 case CPUID_8000_0002:
90                 case CPUID_8000_0003:
91                 case CPUID_8000_0004:
92                 case CPUID_8000_0006:
93                 case CPUID_8000_0008:
94                         cpuid_count(*eax, *ecx, regs);
95                         break;
96
97                 case CPUID_8000_0001:
98                         /*
99                          * Hide rdtscp/ia32_tsc_aux until we know how
100                          * to deal with them.
101                          */
102                         cpuid_count(*eax, *ecx, regs);
103                         regs[3] &= ~AMDID_RDTSCP;
104                         break;
105
106                 case CPUID_8000_0007:
107                         cpuid_count(*eax, *ecx, regs);
108                         /*
109                          * If the host TSCs are not synchronized across
110                          * physical cpus then we cannot advertise an
111                          * invariant tsc to a vcpu.
112                          *
113                          * XXX This still falls short because the vcpu
114                          * can observe the TSC moving backwards as it
115                          * migrates across physical cpus. But at least
116                          * it should discourage the guest from using the
117                          * TSC to keep track of time.
118                          */
119                         if (!smp_tsc)
120                                 regs[3] &= ~AMDPM_TSC_INVARIANT;
121                         break;
122
123                 case CPUID_0000_0001:
124                         do_cpuid(1, regs);
125
126                         error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state);
127                         if (error) {
128                                 panic("x86_emulate_cpuid: error %d "
129                                       "fetching x2apic state", error);
130                         }
131
132                         /*
133                          * Override the APIC ID only in ebx
134                          */
135                         regs[1] &= ~(CPUID_LOCAL_APIC_ID);
136                         regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT);
137
138                         /*
139                          * Don't expose VMX, SpeedStep or TME capability.
140                          * Advertise x2APIC capability and Hypervisor guest.
141                          */
142                         regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2);
143
144                         regs[2] |= CPUID2_HV;
145
146                         if (x2apic_state != X2APIC_DISABLED)
147                                 regs[2] |= CPUID2_X2APIC;
148
149                         /*
150                          * Hide xsave/osxsave/avx until the FPU save/restore
151                          * issues are resolved
152                          */
153                         regs[2] &= ~(CPUID2_XSAVE | CPUID2_OSXSAVE |
154                                      CPUID2_AVX);
155
156                         /*
157                          * Hide monitor/mwait until we know how to deal with
158                          * these instructions.
159                          */
160                         regs[2] &= ~CPUID2_MON;
161
162                         /*
163                          * Hide the performance and debug features.
164                          */
165                         regs[2] &= ~CPUID2_PDCM;
166
167                         /*
168                          * No TSC deadline support in the APIC yet
169                          */
170                         regs[2] &= ~CPUID2_TSCDLT;
171
172                         /*
173                          * Hide thermal monitoring
174                          */
175                         regs[3] &= ~(CPUID_ACPI | CPUID_TM);
176                         
177                         /*
178                          * Machine check handling is done in the host.
179                          * Hide MTRR capability.
180                          */
181                         regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR);
182
183                         /*
184                         * Hide the debug store capability.
185                         */
186                         regs[3] &= ~CPUID_DS;
187
188                         /*
189                          * Disable multi-core.
190                          */
191                         regs[1] &= ~CPUID_HTT_CORES;
192                         regs[3] &= ~CPUID_HTT;
193                         break;
194
195                 case CPUID_0000_0004:
196                         do_cpuid(4, regs);
197
198                         /*
199                          * Do not expose topology.
200                          */
201                         regs[0] &= 0xffff8000;
202                         regs[0] |= 0x04008000;
203                         break;
204
205                 case CPUID_0000_0007:
206                         regs[0] = 0;
207                         regs[1] = 0;
208                         regs[2] = 0;
209                         regs[3] = 0;
210
211                         /* leaf 0 */
212                         if (*ecx == 0) {
213                                 error = vm_get_capability(vm, vcpu_id,
214                                     VM_CAP_ENABLE_INVPCID, &enable_invpcid);
215                                 if (error == 0 && enable_invpcid)
216                                         regs[1] |= CPUID_STDEXT_INVPCID;
217                         }
218                         break;
219
220                 case CPUID_0000_0006:
221                 case CPUID_0000_000A:
222                 case CPUID_0000_000D:
223                         /*
224                          * Handle the access, but report 0 for
225                          * all options
226                          */
227                         regs[0] = 0;
228                         regs[1] = 0;
229                         regs[2] = 0;
230                         regs[3] = 0;
231                         break;
232
233                 case CPUID_0000_000B:
234                         /*
235                          * Processor topology enumeration
236                          */
237                         regs[0] = 0;
238                         regs[1] = 0;
239                         regs[2] = *ecx & 0xff;
240                         regs[3] = vcpu_id;
241                         break;
242
243                 case 0x40000000:
244                         regs[0] = CPUID_VM_HIGH;
245                         bcopy(bhyve_id, &regs[1], 4);
246                         bcopy(bhyve_id + 4, &regs[2], 4);
247                         bcopy(bhyve_id + 8, &regs[3], 4);
248                         break;
249
250                 default:
251                         /*
252                          * The leaf value has already been clamped so
253                          * simply pass this through, keeping count of
254                          * how many unhandled leaf values have been seen.
255                          */
256                         atomic_add_long(&bhyve_xcpuids, 1);
257                         cpuid_count(*eax, *ecx, regs);
258                         break;
259         }
260
261         *eax = regs[0];
262         *ebx = regs[1];
263         *ecx = regs[2];
264         *edx = regs[3];
265
266         return (1);
267 }