x86.c revision 249324
1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD: head/sys/amd64/vmm/x86.c 249324 2013-04-10 05:59:07Z neel $ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#include <sys/cdefs.h> 30221828Sgrehan__FBSDID("$FreeBSD: head/sys/amd64/vmm/x86.c 249324 2013-04-10 05:59:07Z neel $"); 31221828Sgrehan 32240941Sneel#include <sys/param.h> 33221828Sgrehan#include <sys/types.h> 34222610Sjhb#include <sys/systm.h> 35240941Sneel#include <sys/cpuset.h> 36221828Sgrehan 37249324Sneel#include <machine/clock.h> 38221828Sgrehan#include <machine/cpufunc.h> 39222610Sjhb#include <machine/md_var.h> 40221828Sgrehan#include <machine/specialreg.h> 41221828Sgrehan 42240941Sneel#include <machine/vmm.h> 43240941Sneel 44221828Sgrehan#include "x86.h" 45221828Sgrehan 46222610Sjhb#define CPUID_VM_HIGH 0x40000000 47222610Sjhb 48222610Sjhbstatic const char bhyve_id[12] = "BHyVE BHyVE "; 49222610Sjhb 50221828Sgrehanint 51240941Sneelx86_emulate_cpuid(struct vm *vm, int vcpu_id, 52240941Sneel uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) 53221828Sgrehan{ 54240941Sneel int error; 55221828Sgrehan unsigned int func, regs[4]; 56240941Sneel enum x2apic_state x2apic_state; 57221828Sgrehan 58222610Sjhb /* 59222610Sjhb * Requests for invalid CPUID levels should map to the highest 60222610Sjhb * available level instead. 61222610Sjhb */ 62222610Sjhb if (cpu_exthigh != 0 && *eax >= 0x80000000) { 63222610Sjhb if (*eax > cpu_exthigh) 64222610Sjhb *eax = cpu_exthigh; 65222610Sjhb } else if (*eax >= 0x40000000) { 66222610Sjhb if (*eax > CPUID_VM_HIGH) 67222610Sjhb *eax = CPUID_VM_HIGH; 68222610Sjhb } else if (*eax > cpu_high) { 69222610Sjhb *eax = cpu_high; 70222610Sjhb } 71221828Sgrehan 72246774Sneel func = *eax; 73246774Sneel 74222610Sjhb /* 75222610Sjhb * In general the approach used for CPU topology is to 76222610Sjhb * advertise a flat topology where all CPUs are packages with 77222610Sjhb * no multi-core or SMT. 78222610Sjhb */ 79222610Sjhb switch (func) { 80221828Sgrehan case CPUID_0000_0000: 81221828Sgrehan case CPUID_0000_0002: 82221828Sgrehan case CPUID_0000_0003: 83221828Sgrehan case CPUID_0000_000A: 84222610Sjhb cpuid_count(*eax, *ecx, regs); 85221828Sgrehan break; 86221828Sgrehan 87221828Sgrehan case CPUID_8000_0000: 88221828Sgrehan case CPUID_8000_0001: 89221828Sgrehan case CPUID_8000_0002: 90221828Sgrehan case CPUID_8000_0003: 91221828Sgrehan case CPUID_8000_0004: 92221828Sgrehan case CPUID_8000_0006: 93221828Sgrehan case CPUID_8000_0008: 94222610Sjhb cpuid_count(*eax, *ecx, regs); 95221828Sgrehan break; 96221828Sgrehan 97249324Sneel case CPUID_8000_0007: 98249324Sneel cpuid_count(*eax, *ecx, regs); 99249324Sneel /* 100249324Sneel * If the host TSCs are not synchronized across 101249324Sneel * physical cpus then we cannot advertise an 102249324Sneel * invariant tsc to a vcpu. 103249324Sneel * 104249324Sneel * XXX This still falls short because the vcpu 105249324Sneel * can observe the TSC moving backwards as it 106249324Sneel * migrates across physical cpus. But at least 107249324Sneel * it should discourage the guest from using the 108249324Sneel * TSC to keep track of time. 109249324Sneel */ 110249324Sneel if (!smp_tsc) 111249324Sneel regs[3] &= ~AMDPM_TSC_INVARIANT; 112249324Sneel break; 113249324Sneel 114221828Sgrehan case CPUID_0000_0001: 115222610Sjhb do_cpuid(1, regs); 116222610Sjhb 117240941Sneel error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state); 118240941Sneel if (error) { 119240941Sneel panic("x86_emulate_cpuid: error %d " 120240941Sneel "fetching x2apic state", error); 121240941Sneel } 122240941Sneel 123221828Sgrehan /* 124221828Sgrehan * Override the APIC ID only in ebx 125221828Sgrehan */ 126222610Sjhb regs[1] &= ~(CPUID_LOCAL_APIC_ID); 127222610Sjhb regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT); 128221828Sgrehan 129221828Sgrehan /* 130222105Sgrehan * Don't expose VMX, SpeedStep or TME capability. 131222610Sjhb * Advertise x2APIC capability and Hypervisor guest. 132221828Sgrehan */ 133222610Sjhb regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2); 134221828Sgrehan 135240941Sneel regs[2] |= CPUID2_HV; 136240941Sneel 137240941Sneel if (x2apic_state != X2APIC_DISABLED) 138240941Sneel regs[2] |= CPUID2_X2APIC; 139240941Sneel 140221828Sgrehan /* 141234939Sgrehan * Hide xsave/osxsave/avx until the FPU save/restore 142234939Sgrehan * issues are resolved 143234939Sgrehan */ 144234939Sgrehan regs[2] &= ~(CPUID2_XSAVE | CPUID2_OSXSAVE | 145234939Sgrehan CPUID2_AVX); 146234939Sgrehan 147234939Sgrehan /* 148242060Sneel * Hide monitor/mwait until we know how to deal with 149242060Sneel * these instructions. 150242060Sneel */ 151242060Sneel regs[2] &= ~CPUID2_MON; 152242060Sneel 153242060Sneel /* 154222105Sgrehan * Hide thermal monitoring 155222105Sgrehan */ 156222105Sgrehan regs[3] &= ~(CPUID_ACPI | CPUID_TM); 157222105Sgrehan 158222105Sgrehan /* 159221828Sgrehan * Machine check handling is done in the host. 160221828Sgrehan * Hide MTRR capability. 161221828Sgrehan */ 162221828Sgrehan regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR); 163221828Sgrehan 164222610Sjhb /* 165222610Sjhb * Disable multi-core. 166222610Sjhb */ 167222610Sjhb regs[1] &= ~CPUID_HTT_CORES; 168222610Sjhb regs[3] &= ~CPUID_HTT; 169221828Sgrehan break; 170221828Sgrehan 171222610Sjhb case CPUID_0000_0004: 172222610Sjhb do_cpuid(4, regs); 173222610Sjhb 174222610Sjhb /* 175222610Sjhb * Do not expose topology. 176222610Sjhb */ 177222610Sjhb regs[0] &= 0xffff8000; 178222610Sjhb regs[0] |= 0x04008000; 179222610Sjhb break; 180222610Sjhb 181222105Sgrehan case CPUID_0000_0006: 182243325Sgrehan case CPUID_0000_0007: 183222105Sgrehan /* 184222105Sgrehan * Handle the access, but report 0 for 185222105Sgrehan * all options 186222105Sgrehan */ 187222105Sgrehan regs[0] = 0; 188222105Sgrehan regs[1] = 0; 189222105Sgrehan regs[2] = 0; 190222105Sgrehan regs[3] = 0; 191222105Sgrehan break; 192222105Sgrehan 193221828Sgrehan case CPUID_0000_000B: 194221828Sgrehan /* 195221828Sgrehan * Processor topology enumeration 196221828Sgrehan */ 197221828Sgrehan regs[0] = 0; 198221828Sgrehan regs[1] = 0; 199221828Sgrehan regs[2] = *ecx & 0xff; 200222610Sjhb regs[3] = vcpu_id; 201221828Sgrehan break; 202221828Sgrehan 203222610Sjhb case 0x40000000: 204222610Sjhb regs[0] = CPUID_VM_HIGH; 205222610Sjhb bcopy(bhyve_id, ®s[1], 4); 206222610Sjhb bcopy(bhyve_id, ®s[2], 4); 207222610Sjhb bcopy(bhyve_id, ®s[3], 4); 208222610Sjhb break; 209221828Sgrehan default: 210222610Sjhb /* XXX: Leaf 5? */ 211221828Sgrehan return (0); 212221828Sgrehan } 213221828Sgrehan 214221828Sgrehan *eax = regs[0]; 215221828Sgrehan *ebx = regs[1]; 216221828Sgrehan *ecx = regs[2]; 217221828Sgrehan *edx = regs[3]; 218221828Sgrehan return (1); 219221828Sgrehan} 220