]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/vmm/x86.c
Import NetBSD libexecinfo 20130822 to contrib
[FreeBSD/FreeBSD.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;
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                          * Hide thermal monitoring
169                          */
170                         regs[3] &= ~(CPUID_ACPI | CPUID_TM);
171                         
172                         /*
173                          * Machine check handling is done in the host.
174                          * Hide MTRR capability.
175                          */
176                         regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR);
177
178                         /*
179                         * Hide the debug store capability.
180                         */
181                         regs[3] &= ~CPUID_DS;
182
183                         /*
184                          * Disable multi-core.
185                          */
186                         regs[1] &= ~CPUID_HTT_CORES;
187                         regs[3] &= ~CPUID_HTT;
188                         break;
189
190                 case CPUID_0000_0004:
191                         do_cpuid(4, regs);
192
193                         /*
194                          * Do not expose topology.
195                          */
196                         regs[0] &= 0xffff8000;
197                         regs[0] |= 0x04008000;
198                         break;
199
200                 case CPUID_0000_0006:
201                 case CPUID_0000_0007:
202                 case CPUID_0000_000A:
203                         /*
204                          * Handle the access, but report 0 for
205                          * all options
206                          */
207                         regs[0] = 0;
208                         regs[1] = 0;
209                         regs[2] = 0;
210                         regs[3] = 0;
211                         break;
212
213                 case CPUID_0000_000B:
214                         /*
215                          * Processor topology enumeration
216                          */
217                         regs[0] = 0;
218                         regs[1] = 0;
219                         regs[2] = *ecx & 0xff;
220                         regs[3] = vcpu_id;
221                         break;
222
223                 case 0x40000000:
224                         regs[0] = CPUID_VM_HIGH;
225                         bcopy(bhyve_id, &regs[1], 4);
226                         bcopy(bhyve_id + 4, &regs[2], 4);
227                         bcopy(bhyve_id + 8, &regs[3], 4);
228                         break;
229
230                 default:
231                         /*
232                          * The leaf value has already been clamped so
233                          * simply pass this through, keeping count of
234                          * how many unhandled leaf values have been seen.
235                          */
236                         atomic_add_long(&bhyve_xcpuids, 1);
237                         cpuid_count(*eax, *ecx, regs);
238                         break;
239         }
240
241         *eax = regs[0];
242         *ebx = regs[1];
243         *ecx = regs[2];
244         *edx = regs[3];
245
246         return (1);
247 }