1bf21cd93STycho Nightingale /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 4bf21cd93STycho Nightingale * Copyright (c) 2011 NetApp, Inc. 5bf21cd93STycho Nightingale * All rights reserved. 6bf21cd93STycho Nightingale * 7bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without 8bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions 9bf21cd93STycho Nightingale * are met: 10bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright 11bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer. 12bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright 13bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the 14bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution. 15bf21cd93STycho Nightingale * 16bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26bf21cd93STycho Nightingale * SUCH DAMAGE. 27bf21cd93STycho Nightingale * 284c87aefeSPatrick Mooney * $FreeBSD$ 29bf21cd93STycho Nightingale */ 30bf21cd93STycho Nightingale /* 31bf21cd93STycho Nightingale * This file and its contents are supplied under the terms of the 32bf21cd93STycho Nightingale * Common Development and Distribution License ("CDDL"), version 1.0. 33bf21cd93STycho Nightingale * You may only use this file in accordance with the terms of version 34bf21cd93STycho Nightingale * 1.0 of the CDDL. 35bf21cd93STycho Nightingale * 36bf21cd93STycho Nightingale * A full copy of the text of the CDDL should have accompanied this 37bf21cd93STycho Nightingale * source. A copy of the CDDL is also available via the Internet at 38bf21cd93STycho Nightingale * http://www.illumos.org/license/CDDL. 39bf21cd93STycho Nightingale * 40bf21cd93STycho Nightingale * Copyright 2014 Pluribus Networks Inc. 414c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 423c5f2a9dSPatrick Mooney * Copyright 2020 Oxide Computer Company 43bf21cd93STycho Nightingale */ 44bf21cd93STycho Nightingale 45bf21cd93STycho Nightingale #include <sys/cdefs.h> 464c87aefeSPatrick Mooney __FBSDID("$FreeBSD$"); 47bf21cd93STycho Nightingale 48bf21cd93STycho Nightingale #include <sys/param.h> 494c87aefeSPatrick Mooney #include <sys/pcpu.h> 50bf21cd93STycho Nightingale #include <sys/systm.h> 514c87aefeSPatrick Mooney #include <sys/sysctl.h> 524c87aefeSPatrick Mooney #include <sys/x86_archext.h> 53bf21cd93STycho Nightingale 54bf21cd93STycho Nightingale #include <machine/clock.h> 55bf21cd93STycho Nightingale #include <machine/cpufunc.h> 56bf21cd93STycho Nightingale #include <machine/md_var.h> 574c87aefeSPatrick Mooney #include <machine/segments.h> 58bf21cd93STycho Nightingale #include <machine/specialreg.h> 59bf21cd93STycho Nightingale 60bf21cd93STycho Nightingale #include <machine/vmm.h> 61*54cf5b63SPatrick Mooney #include <sys/vmm_kernel.h> 62bf21cd93STycho Nightingale 634c87aefeSPatrick Mooney #include "vmm_host.h" 644c87aefeSPatrick Mooney #include "vmm_util.h" 65bf21cd93STycho Nightingale 664c87aefeSPatrick Mooney SYSCTL_DECL(_hw_vmm); 674c87aefeSPatrick Mooney 68bf21cd93STycho Nightingale #define CPUID_VM_HIGH 0x40000000 69bf21cd93STycho Nightingale 70bf21cd93STycho Nightingale static const char bhyve_id[12] = "bhyve bhyve "; 71bf21cd93STycho Nightingale 722699b94cSPatrick Mooney /* Number of times an unknown cpuid leaf was accessed */ 73bf21cd93STycho Nightingale static uint64_t bhyve_xcpuids; 744c87aefeSPatrick Mooney 754c87aefeSPatrick Mooney static int cpuid_leaf_b = 1; 764c87aefeSPatrick Mooney 779250eb13SPatrick Mooney /* 789250eb13SPatrick Mooney * Force exposition of the invariant TSC capability, regardless of whether the 799250eb13SPatrick Mooney * host CPU reports having it. 809250eb13SPatrick Mooney */ 819250eb13SPatrick Mooney static int vmm_force_invariant_tsc = 0; 829250eb13SPatrick Mooney 83*54cf5b63SPatrick Mooney #define CPUID_0000_0000 (0x0) 84*54cf5b63SPatrick Mooney #define CPUID_0000_0001 (0x1) 85*54cf5b63SPatrick Mooney #define CPUID_0000_0002 (0x2) 86*54cf5b63SPatrick Mooney #define CPUID_0000_0003 (0x3) 87*54cf5b63SPatrick Mooney #define CPUID_0000_0004 (0x4) 88*54cf5b63SPatrick Mooney #define CPUID_0000_0006 (0x6) 89*54cf5b63SPatrick Mooney #define CPUID_0000_0007 (0x7) 90*54cf5b63SPatrick Mooney #define CPUID_0000_000A (0xA) 91*54cf5b63SPatrick Mooney #define CPUID_0000_000B (0xB) 92*54cf5b63SPatrick Mooney #define CPUID_0000_000D (0xD) 93*54cf5b63SPatrick Mooney #define CPUID_0000_000F (0xF) 94*54cf5b63SPatrick Mooney #define CPUID_0000_0010 (0x10) 95*54cf5b63SPatrick Mooney #define CPUID_0000_0015 (0x15) 96*54cf5b63SPatrick Mooney #define CPUID_8000_0000 (0x80000000) 97*54cf5b63SPatrick Mooney #define CPUID_8000_0001 (0x80000001) 98*54cf5b63SPatrick Mooney #define CPUID_8000_0002 (0x80000002) 99*54cf5b63SPatrick Mooney #define CPUID_8000_0003 (0x80000003) 100*54cf5b63SPatrick Mooney #define CPUID_8000_0004 (0x80000004) 101*54cf5b63SPatrick Mooney #define CPUID_8000_0006 (0x80000006) 102*54cf5b63SPatrick Mooney #define CPUID_8000_0007 (0x80000007) 103*54cf5b63SPatrick Mooney #define CPUID_8000_0008 (0x80000008) 104*54cf5b63SPatrick Mooney #define CPUID_8000_001D (0x8000001D) 105*54cf5b63SPatrick Mooney #define CPUID_8000_001E (0x8000001E) 106*54cf5b63SPatrick Mooney 107*54cf5b63SPatrick Mooney /* 108*54cf5b63SPatrick Mooney * CPUID instruction Fn0000_0001: 109*54cf5b63SPatrick Mooney */ 110*54cf5b63SPatrick Mooney #define CPUID_0000_0001_APICID_MASK (0xff<<24) 111*54cf5b63SPatrick Mooney #define CPUID_0000_0001_APICID_SHIFT 24 112*54cf5b63SPatrick Mooney 113*54cf5b63SPatrick Mooney /* 114*54cf5b63SPatrick Mooney * CPUID instruction Fn0000_0001 ECX 115*54cf5b63SPatrick Mooney */ 116*54cf5b63SPatrick Mooney #define CPUID_0000_0001_FEAT0_VMX (1<<5) 117*54cf5b63SPatrick Mooney 118*54cf5b63SPatrick Mooney 1194c87aefeSPatrick Mooney /* 1204c87aefeSPatrick Mooney * Round up to the next power of two, if necessary, and then take log2. 1214c87aefeSPatrick Mooney * Returns -1 if argument is zero. 1224c87aefeSPatrick Mooney */ 1234c87aefeSPatrick Mooney static __inline int 1242699b94cSPatrick Mooney log2(uint_t x) 1254c87aefeSPatrick Mooney { 1264c87aefeSPatrick Mooney 1274c87aefeSPatrick Mooney return (fls(x << (1 - powerof2(x))) - 1); 1284c87aefeSPatrick Mooney } 129bf21cd93STycho Nightingale 130bf21cd93STycho Nightingale int 1313c5f2a9dSPatrick Mooney x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint64_t *rax, uint64_t *rbx, 1323c5f2a9dSPatrick Mooney uint64_t *rcx, uint64_t *rdx) 133bf21cd93STycho Nightingale { 1344c87aefeSPatrick Mooney const struct xsave_limits *limits; 1354c87aefeSPatrick Mooney uint64_t cr4; 1364c87aefeSPatrick Mooney int error, enable_invpcid, level, width = 0, x2apic_id = 0; 1373c5f2a9dSPatrick Mooney unsigned int func, regs[4], logical_cpus = 0, param; 138bf21cd93STycho Nightingale enum x2apic_state x2apic_state; 1394c87aefeSPatrick Mooney uint16_t cores, maxcpus, sockets, threads; 1404c87aefeSPatrick Mooney 1413c5f2a9dSPatrick Mooney /* 1423c5f2a9dSPatrick Mooney * The function of CPUID is controlled through the provided value of 1433c5f2a9dSPatrick Mooney * %eax (and secondarily %ecx, for certain leaf data). 1443c5f2a9dSPatrick Mooney */ 1453c5f2a9dSPatrick Mooney func = (uint32_t)*rax; 1463c5f2a9dSPatrick Mooney param = (uint32_t)*rcx; 1473c5f2a9dSPatrick Mooney 148bf21cd93STycho Nightingale /* 149bf21cd93STycho Nightingale * Requests for invalid CPUID levels should map to the highest 150bf21cd93STycho Nightingale * available level instead. 151bf21cd93STycho Nightingale */ 1523c5f2a9dSPatrick Mooney if (cpu_exthigh != 0 && func >= 0x80000000) { 1533c5f2a9dSPatrick Mooney if (func > cpu_exthigh) 1543c5f2a9dSPatrick Mooney func = cpu_exthigh; 1553c5f2a9dSPatrick Mooney } else if (func >= 0x40000000) { 1563c5f2a9dSPatrick Mooney if (func > CPUID_VM_HIGH) 1573c5f2a9dSPatrick Mooney func = CPUID_VM_HIGH; 1583c5f2a9dSPatrick Mooney } else if (func > cpu_high) { 1593c5f2a9dSPatrick Mooney func = cpu_high; 160bf21cd93STycho Nightingale } 161bf21cd93STycho Nightingale 162bf21cd93STycho Nightingale /* 163bf21cd93STycho Nightingale * In general the approach used for CPU topology is to 164bf21cd93STycho Nightingale * advertise a flat topology where all CPUs are packages with 165bf21cd93STycho Nightingale * no multi-core or SMT. 166bf21cd93STycho Nightingale */ 167bf21cd93STycho Nightingale switch (func) { 168bf21cd93STycho Nightingale /* 169bf21cd93STycho Nightingale * Pass these through to the guest 170bf21cd93STycho Nightingale */ 171bf21cd93STycho Nightingale case CPUID_0000_0000: 172bf21cd93STycho Nightingale case CPUID_0000_0002: 173bf21cd93STycho Nightingale case CPUID_0000_0003: 174bf21cd93STycho Nightingale case CPUID_8000_0000: 175bf21cd93STycho Nightingale case CPUID_8000_0002: 176bf21cd93STycho Nightingale case CPUID_8000_0003: 177bf21cd93STycho Nightingale case CPUID_8000_0004: 178bf21cd93STycho Nightingale case CPUID_8000_0006: 1793c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 1804c87aefeSPatrick Mooney break; 181bf21cd93STycho Nightingale case CPUID_8000_0008: 1823c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 183154972afSPatrick Mooney if (vmm_is_svm()) { 1844c87aefeSPatrick Mooney /* 1854c87aefeSPatrick Mooney * As on Intel (0000_0007:0, EDX), mask out 1864c87aefeSPatrick Mooney * unsupported or unsafe AMD extended features 1874c87aefeSPatrick Mooney * (8000_0008 EBX). 1884c87aefeSPatrick Mooney */ 1894c87aefeSPatrick Mooney regs[1] &= (AMDFEID_CLZERO | AMDFEID_IRPERF | 1904c87aefeSPatrick Mooney AMDFEID_XSAVEERPTR); 1914c87aefeSPatrick Mooney 1924c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 1934c87aefeSPatrick Mooney &maxcpus); 1944c87aefeSPatrick Mooney /* 1954c87aefeSPatrick Mooney * Here, width is ApicIdCoreIdSize, present on 1964c87aefeSPatrick Mooney * at least Family 15h and newer. It 1974c87aefeSPatrick Mooney * represents the "number of bits in the 1984c87aefeSPatrick Mooney * initial apicid that indicate thread id 1994c87aefeSPatrick Mooney * within a package." 2004c87aefeSPatrick Mooney * 2014c87aefeSPatrick Mooney * Our topo_probe_amd() uses it for 2024c87aefeSPatrick Mooney * pkg_id_shift and other OSes may rely on it. 2034c87aefeSPatrick Mooney */ 2044c87aefeSPatrick Mooney width = MIN(0xF, log2(threads * cores)); 2054c87aefeSPatrick Mooney if (width < 0x4) 2064c87aefeSPatrick Mooney width = 0; 2074c87aefeSPatrick Mooney logical_cpus = MIN(0xFF, threads * cores - 1); 2082699b94cSPatrick Mooney regs[2] = (width << AMDID_COREID_SIZE_SHIFT) | 2092699b94cSPatrick Mooney logical_cpus; 2104c87aefeSPatrick Mooney } 211bf21cd93STycho Nightingale break; 212bf21cd93STycho Nightingale 213bf21cd93STycho Nightingale case CPUID_8000_0001: 2143c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 2154c87aefeSPatrick Mooney 2164c87aefeSPatrick Mooney /* 2174c87aefeSPatrick Mooney * Hide SVM from guest. 2184c87aefeSPatrick Mooney */ 2194c87aefeSPatrick Mooney regs[2] &= ~AMDID2_SVM; 2204c87aefeSPatrick Mooney 2214c87aefeSPatrick Mooney /* 2224c87aefeSPatrick Mooney * Don't advertise extended performance counter MSRs 2234c87aefeSPatrick Mooney * to the guest. 2244c87aefeSPatrick Mooney */ 2254c87aefeSPatrick Mooney regs[2] &= ~AMDID2_PCXC; 2264c87aefeSPatrick Mooney regs[2] &= ~AMDID2_PNXC; 2274c87aefeSPatrick Mooney regs[2] &= ~AMDID2_PTSCEL2I; 2284c87aefeSPatrick Mooney 2294c87aefeSPatrick Mooney /* 2304c87aefeSPatrick Mooney * Don't advertise Instruction Based Sampling feature. 2314c87aefeSPatrick Mooney */ 2324c87aefeSPatrick Mooney regs[2] &= ~AMDID2_IBS; 2334c87aefeSPatrick Mooney 2344c87aefeSPatrick Mooney /* NodeID MSR not available */ 2354c87aefeSPatrick Mooney regs[2] &= ~AMDID2_NODE_ID; 2364c87aefeSPatrick Mooney 2374c87aefeSPatrick Mooney /* Don't advertise the OS visible workaround feature */ 2384c87aefeSPatrick Mooney regs[2] &= ~AMDID2_OSVW; 2394c87aefeSPatrick Mooney 2404c87aefeSPatrick Mooney /* Hide mwaitx/monitorx capability from the guest */ 2414c87aefeSPatrick Mooney regs[2] &= ~AMDID2_MWAITX; 2424c87aefeSPatrick Mooney 2434c87aefeSPatrick Mooney #ifndef __FreeBSD__ 2444c87aefeSPatrick Mooney /* 2454c87aefeSPatrick Mooney * Detection routines for TCE and FFXSR are missing 2464c87aefeSPatrick Mooney * from our vm_cpuid_capability() detection logic 2474c87aefeSPatrick Mooney * today. Mask them out until that is remedied. 2484c87aefeSPatrick Mooney * They do not appear to be in common usage, so their 2494c87aefeSPatrick Mooney * absence should not cause undue trouble. 2504c87aefeSPatrick Mooney */ 2514c87aefeSPatrick Mooney regs[2] &= ~AMDID2_TCE; 2524c87aefeSPatrick Mooney regs[3] &= ~AMDID_FFXSR; 2534c87aefeSPatrick Mooney #endif 2544c87aefeSPatrick Mooney 255bf21cd93STycho Nightingale /* 256bf21cd93STycho Nightingale * Hide rdtscp/ia32_tsc_aux until we know how 257bf21cd93STycho Nightingale * to deal with them. 258bf21cd93STycho Nightingale */ 259bf21cd93STycho Nightingale regs[3] &= ~AMDID_RDTSCP; 260bf21cd93STycho Nightingale break; 261bf21cd93STycho Nightingale 262bf21cd93STycho Nightingale case CPUID_8000_0007: 2639250eb13SPatrick Mooney cpuid_count(func, param, regs); 264bf21cd93STycho Nightingale /* 2654c87aefeSPatrick Mooney * AMD uses this leaf to advertise the processor's 2664c87aefeSPatrick Mooney * power monitoring and RAS capabilities. These 2674c87aefeSPatrick Mooney * features are hardware-specific and exposing 2684c87aefeSPatrick Mooney * them to a guest doesn't make a lot of sense. 2694c87aefeSPatrick Mooney * 2704c87aefeSPatrick Mooney * Intel uses this leaf only to advertise the 2714c87aefeSPatrick Mooney * "Invariant TSC" feature with all other bits 2724c87aefeSPatrick Mooney * being reserved (set to zero). 2734c87aefeSPatrick Mooney */ 2744c87aefeSPatrick Mooney regs[0] = 0; 2754c87aefeSPatrick Mooney regs[1] = 0; 2764c87aefeSPatrick Mooney regs[2] = 0; 2774c87aefeSPatrick Mooney 2784c87aefeSPatrick Mooney /* 2799250eb13SPatrick Mooney * If the host system possesses an invariant TSC, then 2809250eb13SPatrick Mooney * it is safe to expose to the guest. 281bf21cd93STycho Nightingale * 2829250eb13SPatrick Mooney * If there is measured skew between host TSCs, it will 2839250eb13SPatrick Mooney * be properly offset so guests do not observe any 2849250eb13SPatrick Mooney * change between CPU migrations. 285bf21cd93STycho Nightingale */ 2869250eb13SPatrick Mooney regs[3] &= AMDPM_TSC_INVARIANT; 2879250eb13SPatrick Mooney 2889250eb13SPatrick Mooney /* 2899250eb13SPatrick Mooney * Since illumos avoids deep C-states on CPUs which do 2909250eb13SPatrick Mooney * not support an invariant TSC, it may be safe (and 2919250eb13SPatrick Mooney * desired) to unconditionally expose that capability to 2929250eb13SPatrick Mooney * the guest. 2939250eb13SPatrick Mooney */ 2949250eb13SPatrick Mooney if (vmm_force_invariant_tsc != 0) { 2954c87aefeSPatrick Mooney regs[3] |= AMDPM_TSC_INVARIANT; 2969250eb13SPatrick Mooney } 2974c87aefeSPatrick Mooney break; 2984c87aefeSPatrick Mooney 2994c87aefeSPatrick Mooney case CPUID_8000_001D: 3004c87aefeSPatrick Mooney /* AMD Cache topology, like 0000_0004 for Intel. */ 301154972afSPatrick Mooney if (!vmm_is_svm()) 3024c87aefeSPatrick Mooney goto default_leaf; 3034c87aefeSPatrick Mooney 3044c87aefeSPatrick Mooney /* 3054c87aefeSPatrick Mooney * Similar to Intel, generate a ficticious cache 3064c87aefeSPatrick Mooney * topology for the guest with L3 shared by the 3074c87aefeSPatrick Mooney * package, and L1 and L2 local to a core. 3084c87aefeSPatrick Mooney */ 3094c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 3104c87aefeSPatrick Mooney &maxcpus); 3113c5f2a9dSPatrick Mooney switch (param) { 3124c87aefeSPatrick Mooney case 0: 3134c87aefeSPatrick Mooney logical_cpus = threads; 3144c87aefeSPatrick Mooney level = 1; 3154c87aefeSPatrick Mooney func = 1; /* data cache */ 3164c87aefeSPatrick Mooney break; 3174c87aefeSPatrick Mooney case 1: 3184c87aefeSPatrick Mooney logical_cpus = threads; 3194c87aefeSPatrick Mooney level = 2; 3204c87aefeSPatrick Mooney func = 3; /* unified cache */ 3214c87aefeSPatrick Mooney break; 3224c87aefeSPatrick Mooney case 2: 3234c87aefeSPatrick Mooney logical_cpus = threads * cores; 3244c87aefeSPatrick Mooney level = 3; 3254c87aefeSPatrick Mooney func = 3; /* unified cache */ 3264c87aefeSPatrick Mooney break; 3274c87aefeSPatrick Mooney default: 3284c87aefeSPatrick Mooney logical_cpus = 0; 3294c87aefeSPatrick Mooney level = 0; 3304c87aefeSPatrick Mooney func = 0; 3314c87aefeSPatrick Mooney break; 3324c87aefeSPatrick Mooney } 3334c87aefeSPatrick Mooney 3344c87aefeSPatrick Mooney logical_cpus = MIN(0xfff, logical_cpus - 1); 3354c87aefeSPatrick Mooney regs[0] = (logical_cpus << 14) | (1 << 8) | 3364c87aefeSPatrick Mooney (level << 5) | func; 3374c87aefeSPatrick Mooney regs[1] = (func > 0) ? (CACHE_LINE_SIZE - 1) : 0; 3384c87aefeSPatrick Mooney regs[2] = 0; 3394c87aefeSPatrick Mooney regs[3] = 0; 3404c87aefeSPatrick Mooney break; 3414c87aefeSPatrick Mooney 3424c87aefeSPatrick Mooney case CPUID_8000_001E: 343154972afSPatrick Mooney /* 344154972afSPatrick Mooney * AMD Family 16h+ and Hygon Family 18h additional 345154972afSPatrick Mooney * identifiers. 346154972afSPatrick Mooney */ 347154972afSPatrick Mooney if (!vmm_is_svm() || CPUID_TO_FAMILY(cpu_id) < 0x16) 3484c87aefeSPatrick Mooney goto default_leaf; 3494c87aefeSPatrick Mooney 3504c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 3514c87aefeSPatrick Mooney &maxcpus); 3524c87aefeSPatrick Mooney regs[0] = vcpu_id; 3534c87aefeSPatrick Mooney threads = MIN(0xFF, threads - 1); 3544c87aefeSPatrick Mooney regs[1] = (threads << 8) | 3554c87aefeSPatrick Mooney (vcpu_id >> log2(threads + 1)); 3564c87aefeSPatrick Mooney /* 3574c87aefeSPatrick Mooney * XXX Bhyve topology cannot yet represent >1 node per 3584c87aefeSPatrick Mooney * processor. 3594c87aefeSPatrick Mooney */ 3604c87aefeSPatrick Mooney regs[2] = 0; 3614c87aefeSPatrick Mooney regs[3] = 0; 362bf21cd93STycho Nightingale break; 363bf21cd93STycho Nightingale 364bf21cd93STycho Nightingale case CPUID_0000_0001: 365bf21cd93STycho Nightingale do_cpuid(1, regs); 366bf21cd93STycho Nightingale 367bf21cd93STycho Nightingale error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state); 368bf21cd93STycho Nightingale if (error) { 369bf21cd93STycho Nightingale panic("x86_emulate_cpuid: error %d " 3702699b94cSPatrick Mooney "fetching x2apic state", error); 371bf21cd93STycho Nightingale } 372bf21cd93STycho Nightingale 373bf21cd93STycho Nightingale /* 374bf21cd93STycho Nightingale * Override the APIC ID only in ebx 375bf21cd93STycho Nightingale */ 376bf21cd93STycho Nightingale regs[1] &= ~(CPUID_LOCAL_APIC_ID); 377bf21cd93STycho Nightingale regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT); 378bf21cd93STycho Nightingale 379bf21cd93STycho Nightingale /* 3804c87aefeSPatrick Mooney * Don't expose VMX, SpeedStep, TME or SMX capability. 381bf21cd93STycho Nightingale * Advertise x2APIC capability and Hypervisor guest. 382bf21cd93STycho Nightingale */ 383bf21cd93STycho Nightingale regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2); 3844c87aefeSPatrick Mooney regs[2] &= ~(CPUID2_SMX); 385bf21cd93STycho Nightingale 386bf21cd93STycho Nightingale regs[2] |= CPUID2_HV; 387bf21cd93STycho Nightingale 388bf21cd93STycho Nightingale if (x2apic_state != X2APIC_DISABLED) 389bf21cd93STycho Nightingale regs[2] |= CPUID2_X2APIC; 3904c87aefeSPatrick Mooney else 3914c87aefeSPatrick Mooney regs[2] &= ~CPUID2_X2APIC; 392bf21cd93STycho Nightingale 393bf21cd93STycho Nightingale /* 3944c87aefeSPatrick Mooney * Only advertise CPUID2_XSAVE in the guest if 3954c87aefeSPatrick Mooney * the host is using XSAVE. 396bf21cd93STycho Nightingale */ 3974c87aefeSPatrick Mooney if (!(regs[2] & CPUID2_OSXSAVE)) 3984c87aefeSPatrick Mooney regs[2] &= ~CPUID2_XSAVE; 3994c87aefeSPatrick Mooney 4004c87aefeSPatrick Mooney /* 4014c87aefeSPatrick Mooney * If CPUID2_XSAVE is being advertised and the 4024c87aefeSPatrick Mooney * guest has set CR4_XSAVE, set 4034c87aefeSPatrick Mooney * CPUID2_OSXSAVE. 4044c87aefeSPatrick Mooney */ 4054c87aefeSPatrick Mooney regs[2] &= ~CPUID2_OSXSAVE; 4064c87aefeSPatrick Mooney if (regs[2] & CPUID2_XSAVE) { 4074c87aefeSPatrick Mooney error = vm_get_register(vm, vcpu_id, 4084c87aefeSPatrick Mooney VM_REG_GUEST_CR4, &cr4); 4094c87aefeSPatrick Mooney if (error) 4104c87aefeSPatrick Mooney panic("x86_emulate_cpuid: error %d " 4112699b94cSPatrick Mooney "fetching %%cr4", error); 4124c87aefeSPatrick Mooney if (cr4 & CR4_XSAVE) 4134c87aefeSPatrick Mooney regs[2] |= CPUID2_OSXSAVE; 4144c87aefeSPatrick Mooney } 415bf21cd93STycho Nightingale 416bf21cd93STycho Nightingale /* 417bf21cd93STycho Nightingale * Hide monitor/mwait until we know how to deal with 418bf21cd93STycho Nightingale * these instructions. 419bf21cd93STycho Nightingale */ 420bf21cd93STycho Nightingale regs[2] &= ~CPUID2_MON; 421bf21cd93STycho Nightingale 4222699b94cSPatrick Mooney /* 423bf21cd93STycho Nightingale * Hide the performance and debug features. 424bf21cd93STycho Nightingale */ 425bf21cd93STycho Nightingale regs[2] &= ~CPUID2_PDCM; 4264c87aefeSPatrick Mooney 427bf21cd93STycho Nightingale /* 428bf21cd93STycho Nightingale * No TSC deadline support in the APIC yet 429bf21cd93STycho Nightingale */ 430bf21cd93STycho Nightingale regs[2] &= ~CPUID2_TSCDLT; 431bf21cd93STycho Nightingale 432bf21cd93STycho Nightingale /* 433bf21cd93STycho Nightingale * Hide thermal monitoring 434bf21cd93STycho Nightingale */ 435bf21cd93STycho Nightingale regs[3] &= ~(CPUID_ACPI | CPUID_TM); 4364c87aefeSPatrick Mooney 437bf21cd93STycho Nightingale /* 4384c87aefeSPatrick Mooney * Hide the debug store capability. 439bf21cd93STycho Nightingale */ 440bf21cd93STycho Nightingale regs[3] &= ~CPUID_DS; 441bf21cd93STycho Nightingale 442bf21cd93STycho Nightingale /* 4434c87aefeSPatrick Mooney * Advertise the Machine Check and MTRR capability. 4444c87aefeSPatrick Mooney * 4454c87aefeSPatrick Mooney * Some guest OSes (e.g. Windows) will not boot if 4464c87aefeSPatrick Mooney * these features are absent. 447bf21cd93STycho Nightingale */ 4484c87aefeSPatrick Mooney regs[3] |= (CPUID_MCA | CPUID_MCE | CPUID_MTRR); 4494c87aefeSPatrick Mooney 4504c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 4514c87aefeSPatrick Mooney &maxcpus); 4524c87aefeSPatrick Mooney logical_cpus = threads * cores; 453bf21cd93STycho Nightingale regs[1] &= ~CPUID_HTT_CORES; 4544c87aefeSPatrick Mooney regs[1] |= (logical_cpus & 0xff) << 16; 4554c87aefeSPatrick Mooney regs[3] |= CPUID_HTT; 456bf21cd93STycho Nightingale break; 457bf21cd93STycho Nightingale 458bf21cd93STycho Nightingale case CPUID_0000_0004: 4593c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 460bf21cd93STycho Nightingale 4614c87aefeSPatrick Mooney if (regs[0] || regs[1] || regs[2] || regs[3]) { 4624c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 4634c87aefeSPatrick Mooney &maxcpus); 4644c87aefeSPatrick Mooney regs[0] &= 0x3ff; 4654c87aefeSPatrick Mooney regs[0] |= (cores - 1) << 26; 4664c87aefeSPatrick Mooney /* 4674c87aefeSPatrick Mooney * Cache topology: 4684c87aefeSPatrick Mooney * - L1 and L2 are shared only by the logical 4694c87aefeSPatrick Mooney * processors in a single core. 4704c87aefeSPatrick Mooney * - L3 and above are shared by all logical 4714c87aefeSPatrick Mooney * processors in the package. 4724c87aefeSPatrick Mooney */ 4734c87aefeSPatrick Mooney logical_cpus = threads; 4744c87aefeSPatrick Mooney level = (regs[0] >> 5) & 0x7; 4754c87aefeSPatrick Mooney if (level >= 3) 4764c87aefeSPatrick Mooney logical_cpus *= cores; 4774c87aefeSPatrick Mooney regs[0] |= (logical_cpus - 1) << 14; 4784c87aefeSPatrick Mooney } 479bf21cd93STycho Nightingale break; 480bf21cd93STycho Nightingale 481bf21cd93STycho Nightingale case CPUID_0000_0007: 4824c87aefeSPatrick Mooney regs[0] = 0; 4834c87aefeSPatrick Mooney regs[1] = 0; 4844c87aefeSPatrick Mooney regs[2] = 0; 4854c87aefeSPatrick Mooney regs[3] = 0; 4864c87aefeSPatrick Mooney 4874c87aefeSPatrick Mooney /* leaf 0 */ 4883c5f2a9dSPatrick Mooney if (param == 0) { 4893c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 4904c87aefeSPatrick Mooney 4914c87aefeSPatrick Mooney /* Only leaf 0 is supported */ 4924c87aefeSPatrick Mooney regs[0] = 0; 4934c87aefeSPatrick Mooney 4944c87aefeSPatrick Mooney /* 4954c87aefeSPatrick Mooney * Expose known-safe features. 4964c87aefeSPatrick Mooney */ 4974c87aefeSPatrick Mooney regs[1] &= (CPUID_STDEXT_FSGSBASE | 4984c87aefeSPatrick Mooney CPUID_STDEXT_BMI1 | CPUID_STDEXT_HLE | 499b0de25cbSAndy Fiddaman CPUID_STDEXT_AVX2 | CPUID_STDEXT_SMEP | 500b0de25cbSAndy Fiddaman CPUID_STDEXT_BMI2 | 5014c87aefeSPatrick Mooney CPUID_STDEXT_ERMS | CPUID_STDEXT_RTM | 5024c87aefeSPatrick Mooney CPUID_STDEXT_AVX512F | 5034c87aefeSPatrick Mooney CPUID_STDEXT_RDSEED | 504b0de25cbSAndy Fiddaman CPUID_STDEXT_SMAP | 5054c87aefeSPatrick Mooney CPUID_STDEXT_AVX512PF | 5064c87aefeSPatrick Mooney CPUID_STDEXT_AVX512ER | 5074c87aefeSPatrick Mooney CPUID_STDEXT_AVX512CD | CPUID_STDEXT_SHA); 5084c87aefeSPatrick Mooney regs[2] = 0; 5094c87aefeSPatrick Mooney regs[3] &= CPUID_STDEXT3_MD_CLEAR; 5104c87aefeSPatrick Mooney 5114c87aefeSPatrick Mooney /* Advertise INVPCID if it is enabled. */ 5124c87aefeSPatrick Mooney error = vm_get_capability(vm, vcpu_id, 5134c87aefeSPatrick Mooney VM_CAP_ENABLE_INVPCID, &enable_invpcid); 5144c87aefeSPatrick Mooney if (error == 0 && enable_invpcid) 5154c87aefeSPatrick Mooney regs[1] |= CPUID_STDEXT_INVPCID; 5164c87aefeSPatrick Mooney } 5174c87aefeSPatrick Mooney break; 5184c87aefeSPatrick Mooney 5194c87aefeSPatrick Mooney case CPUID_0000_0006: 5204c87aefeSPatrick Mooney regs[0] = CPUTPM1_ARAT; 5214c87aefeSPatrick Mooney regs[1] = 0; 5224c87aefeSPatrick Mooney regs[2] = 0; 5234c87aefeSPatrick Mooney regs[3] = 0; 5244c87aefeSPatrick Mooney break; 5254c87aefeSPatrick Mooney 526bf21cd93STycho Nightingale case CPUID_0000_000A: 527bf21cd93STycho Nightingale /* 528bf21cd93STycho Nightingale * Handle the access, but report 0 for 529bf21cd93STycho Nightingale * all options 530bf21cd93STycho Nightingale */ 531bf21cd93STycho Nightingale regs[0] = 0; 532bf21cd93STycho Nightingale regs[1] = 0; 533bf21cd93STycho Nightingale regs[2] = 0; 534bf21cd93STycho Nightingale regs[3] = 0; 535bf21cd93STycho Nightingale break; 536bf21cd93STycho Nightingale 537bf21cd93STycho Nightingale case CPUID_0000_000B: 538bf21cd93STycho Nightingale /* 5394c87aefeSPatrick Mooney * Intel processor topology enumeration 540bf21cd93STycho Nightingale */ 5414c87aefeSPatrick Mooney if (vmm_is_intel()) { 5424c87aefeSPatrick Mooney vm_get_topology(vm, &sockets, &cores, &threads, 5434c87aefeSPatrick Mooney &maxcpus); 5443c5f2a9dSPatrick Mooney if (param == 0) { 5454c87aefeSPatrick Mooney logical_cpus = threads; 5464c87aefeSPatrick Mooney width = log2(logical_cpus); 5474c87aefeSPatrick Mooney level = CPUID_TYPE_SMT; 5484c87aefeSPatrick Mooney x2apic_id = vcpu_id; 5494c87aefeSPatrick Mooney } 5504c87aefeSPatrick Mooney 5513c5f2a9dSPatrick Mooney if (param == 1) { 5524c87aefeSPatrick Mooney logical_cpus = threads * cores; 5534c87aefeSPatrick Mooney width = log2(logical_cpus); 5544c87aefeSPatrick Mooney level = CPUID_TYPE_CORE; 5554c87aefeSPatrick Mooney x2apic_id = vcpu_id; 5564c87aefeSPatrick Mooney } 5574c87aefeSPatrick Mooney 5583c5f2a9dSPatrick Mooney if (!cpuid_leaf_b || param >= 2) { 5594c87aefeSPatrick Mooney width = 0; 5604c87aefeSPatrick Mooney logical_cpus = 0; 5614c87aefeSPatrick Mooney level = 0; 5624c87aefeSPatrick Mooney x2apic_id = 0; 5634c87aefeSPatrick Mooney } 5644c87aefeSPatrick Mooney 5654c87aefeSPatrick Mooney regs[0] = width & 0x1f; 5664c87aefeSPatrick Mooney regs[1] = logical_cpus & 0xffff; 5673c5f2a9dSPatrick Mooney regs[2] = (level << 8) | (param & 0xff); 5684c87aefeSPatrick Mooney regs[3] = x2apic_id; 5694c87aefeSPatrick Mooney } else { 5704c87aefeSPatrick Mooney regs[0] = 0; 5714c87aefeSPatrick Mooney regs[1] = 0; 5724c87aefeSPatrick Mooney regs[2] = 0; 5734c87aefeSPatrick Mooney regs[3] = 0; 5744c87aefeSPatrick Mooney } 5754c87aefeSPatrick Mooney break; 5764c87aefeSPatrick Mooney 5774c87aefeSPatrick Mooney case CPUID_0000_000D: 5784c87aefeSPatrick Mooney limits = vmm_get_xsave_limits(); 5794c87aefeSPatrick Mooney if (!limits->xsave_enabled) { 5804c87aefeSPatrick Mooney regs[0] = 0; 5814c87aefeSPatrick Mooney regs[1] = 0; 5824c87aefeSPatrick Mooney regs[2] = 0; 5834c87aefeSPatrick Mooney regs[3] = 0; 5844c87aefeSPatrick Mooney break; 5854c87aefeSPatrick Mooney } 5864c87aefeSPatrick Mooney 5873c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 5883c5f2a9dSPatrick Mooney switch (param) { 5894c87aefeSPatrick Mooney case 0: 5904c87aefeSPatrick Mooney /* 5914c87aefeSPatrick Mooney * Only permit the guest to use bits 5924c87aefeSPatrick Mooney * that are active in the host in 5934c87aefeSPatrick Mooney * %xcr0. Also, claim that the 5944c87aefeSPatrick Mooney * maximum save area size is 5954c87aefeSPatrick Mooney * equivalent to the host's current 5964c87aefeSPatrick Mooney * save area size. Since this runs 5974c87aefeSPatrick Mooney * "inside" of vmrun(), it runs with 5984c87aefeSPatrick Mooney * the guest's xcr0, so the current 5994c87aefeSPatrick Mooney * save area size is correct as-is. 6004c87aefeSPatrick Mooney */ 6014c87aefeSPatrick Mooney regs[0] &= limits->xcr0_allowed; 6024c87aefeSPatrick Mooney regs[2] = limits->xsave_max_size; 6034c87aefeSPatrick Mooney regs[3] &= (limits->xcr0_allowed >> 32); 6044c87aefeSPatrick Mooney break; 6054c87aefeSPatrick Mooney case 1: 6064c87aefeSPatrick Mooney /* Only permit XSAVEOPT. */ 6074c87aefeSPatrick Mooney regs[0] &= CPUID_EXTSTATE_XSAVEOPT; 6084c87aefeSPatrick Mooney regs[1] = 0; 6094c87aefeSPatrick Mooney regs[2] = 0; 6104c87aefeSPatrick Mooney regs[3] = 0; 6114c87aefeSPatrick Mooney break; 6124c87aefeSPatrick Mooney default: 6134c87aefeSPatrick Mooney /* 6144c87aefeSPatrick Mooney * If the leaf is for a permitted feature, 6154c87aefeSPatrick Mooney * pass through as-is, otherwise return 6164c87aefeSPatrick Mooney * all zeroes. 6174c87aefeSPatrick Mooney */ 6183c5f2a9dSPatrick Mooney if (!(limits->xcr0_allowed & (1ul << param))) { 6194c87aefeSPatrick Mooney regs[0] = 0; 6204c87aefeSPatrick Mooney regs[1] = 0; 6214c87aefeSPatrick Mooney regs[2] = 0; 6224c87aefeSPatrick Mooney regs[3] = 0; 6234c87aefeSPatrick Mooney } 6244c87aefeSPatrick Mooney break; 6254c87aefeSPatrick Mooney } 626bf21cd93STycho Nightingale break; 627bf21cd93STycho Nightingale 6281a5f1879SPatrick Mooney case CPUID_0000_000F: 6291a5f1879SPatrick Mooney case CPUID_0000_0010: 6301a5f1879SPatrick Mooney /* 6311a5f1879SPatrick Mooney * Do not report any Resource Director Technology 6321a5f1879SPatrick Mooney * capabilities. Exposing control of cache or memory 6331a5f1879SPatrick Mooney * controller resource partitioning to the guest is not 6341a5f1879SPatrick Mooney * at all sensible. 6351a5f1879SPatrick Mooney * 6361a5f1879SPatrick Mooney * This is already hidden at a high level by masking of 6371a5f1879SPatrick Mooney * leaf 0x7. Even still, a guest may look here for 6381a5f1879SPatrick Mooney * detailed capability information. 6391a5f1879SPatrick Mooney */ 6401a5f1879SPatrick Mooney regs[0] = 0; 6411a5f1879SPatrick Mooney regs[1] = 0; 6421a5f1879SPatrick Mooney regs[2] = 0; 6431a5f1879SPatrick Mooney regs[3] = 0; 6441a5f1879SPatrick Mooney break; 6451a5f1879SPatrick Mooney 646154972afSPatrick Mooney case CPUID_0000_0015: 647154972afSPatrick Mooney /* 648154972afSPatrick Mooney * Don't report CPU TSC/Crystal ratio and clock 649154972afSPatrick Mooney * values since guests may use these to derive the 650154972afSPatrick Mooney * local APIC frequency.. 651154972afSPatrick Mooney */ 652154972afSPatrick Mooney regs[0] = 0; 653154972afSPatrick Mooney regs[1] = 0; 654154972afSPatrick Mooney regs[2] = 0; 655154972afSPatrick Mooney regs[3] = 0; 656154972afSPatrick Mooney break; 657154972afSPatrick Mooney 658bf21cd93STycho Nightingale case 0x40000000: 659bf21cd93STycho Nightingale regs[0] = CPUID_VM_HIGH; 660bf21cd93STycho Nightingale bcopy(bhyve_id, ®s[1], 4); 661bf21cd93STycho Nightingale bcopy(bhyve_id + 4, ®s[2], 4); 662bf21cd93STycho Nightingale bcopy(bhyve_id + 8, ®s[3], 4); 663bf21cd93STycho Nightingale break; 664bf21cd93STycho Nightingale 665bf21cd93STycho Nightingale default: 6664c87aefeSPatrick Mooney default_leaf: 667bf21cd93STycho Nightingale /* 668bf21cd93STycho Nightingale * The leaf value has already been clamped so 669bf21cd93STycho Nightingale * simply pass this through, keeping count of 670bf21cd93STycho Nightingale * how many unhandled leaf values have been seen. 671bf21cd93STycho Nightingale */ 672bf21cd93STycho Nightingale atomic_add_long(&bhyve_xcpuids, 1); 6733c5f2a9dSPatrick Mooney cpuid_count(func, param, regs); 674bf21cd93STycho Nightingale break; 675bf21cd93STycho Nightingale } 676bf21cd93STycho Nightingale 6773c5f2a9dSPatrick Mooney /* 6783c5f2a9dSPatrick Mooney * CPUID clears the upper 32-bits of the long-mode registers. 6793c5f2a9dSPatrick Mooney */ 6803c5f2a9dSPatrick Mooney *rax = regs[0]; 6813c5f2a9dSPatrick Mooney *rbx = regs[1]; 6823c5f2a9dSPatrick Mooney *rcx = regs[2]; 6833c5f2a9dSPatrick Mooney *rdx = regs[3]; 684bf21cd93STycho Nightingale 685bf21cd93STycho Nightingale return (1); 686bf21cd93STycho Nightingale } 6874c87aefeSPatrick Mooney 688*54cf5b63SPatrick Mooney /* 689*54cf5b63SPatrick Mooney * Return 'true' if the capability 'cap' is enabled in this virtual cpu 690*54cf5b63SPatrick Mooney * and 'false' otherwise. 691*54cf5b63SPatrick Mooney */ 6924c87aefeSPatrick Mooney bool 6934c87aefeSPatrick Mooney vm_cpuid_capability(struct vm *vm, int vcpuid, enum vm_cpuid_capability cap) 6944c87aefeSPatrick Mooney { 6954c87aefeSPatrick Mooney bool rv; 6964c87aefeSPatrick Mooney 6974c87aefeSPatrick Mooney KASSERT(cap > 0 && cap < VCC_LAST, ("%s: invalid vm_cpu_capability %d", 6984c87aefeSPatrick Mooney __func__, cap)); 6994c87aefeSPatrick Mooney 7004c87aefeSPatrick Mooney /* 7014c87aefeSPatrick Mooney * Simply passthrough the capabilities of the host cpu for now. 7024c87aefeSPatrick Mooney */ 7034c87aefeSPatrick Mooney rv = false; 7044c87aefeSPatrick Mooney switch (cap) { 7054c87aefeSPatrick Mooney #ifdef __FreeBSD__ 7064c87aefeSPatrick Mooney case VCC_NO_EXECUTE: 7074c87aefeSPatrick Mooney if (amd_feature & AMDID_NX) 7084c87aefeSPatrick Mooney rv = true; 7094c87aefeSPatrick Mooney break; 7104c87aefeSPatrick Mooney case VCC_FFXSR: 7114c87aefeSPatrick Mooney if (amd_feature & AMDID_FFXSR) 7124c87aefeSPatrick Mooney rv = true; 7134c87aefeSPatrick Mooney break; 7144c87aefeSPatrick Mooney case VCC_TCE: 7154c87aefeSPatrick Mooney if (amd_feature2 & AMDID2_TCE) 7164c87aefeSPatrick Mooney rv = true; 7174c87aefeSPatrick Mooney break; 7184c87aefeSPatrick Mooney #else 7194c87aefeSPatrick Mooney case VCC_NO_EXECUTE: 7204c87aefeSPatrick Mooney if (is_x86_feature(x86_featureset, X86FSET_NX)) 7214c87aefeSPatrick Mooney rv = true; 7224c87aefeSPatrick Mooney break; 7234c87aefeSPatrick Mooney /* XXXJOY: No kernel detection for FFXR or TCE at present, so ignore */ 7244c87aefeSPatrick Mooney case VCC_FFXSR: 7254c87aefeSPatrick Mooney case VCC_TCE: 7264c87aefeSPatrick Mooney break; 7274c87aefeSPatrick Mooney #endif 7284c87aefeSPatrick Mooney default: 7294c87aefeSPatrick Mooney panic("%s: unknown vm_cpu_capability %d", __func__, cap); 7304c87aefeSPatrick Mooney } 7314c87aefeSPatrick Mooney return (rv); 7324c87aefeSPatrick Mooney } 733*54cf5b63SPatrick Mooney 734*54cf5b63SPatrick Mooney bool 735*54cf5b63SPatrick Mooney validate_guest_xcr0(uint64_t val, uint64_t limit_mask) 736*54cf5b63SPatrick Mooney { 737*54cf5b63SPatrick Mooney /* x87 feature must be enabled */ 738*54cf5b63SPatrick Mooney if ((val & XFEATURE_ENABLED_X87) == 0) { 739*54cf5b63SPatrick Mooney return (false); 740*54cf5b63SPatrick Mooney } 741*54cf5b63SPatrick Mooney /* AVX cannot be enabled without SSE */ 742*54cf5b63SPatrick Mooney if ((val & (XFEATURE_ENABLED_SSE | XFEATURE_ENABLED_AVX)) == 743*54cf5b63SPatrick Mooney XFEATURE_ENABLED_SSE) { 744*54cf5b63SPatrick Mooney return (false); 745*54cf5b63SPatrick Mooney } 746*54cf5b63SPatrick Mooney /* No bits should be outside what we dictate to be allowed */ 747*54cf5b63SPatrick Mooney if ((val & ~limit_mask) != 0) { 748*54cf5b63SPatrick Mooney return (false); 749*54cf5b63SPatrick Mooney } 750*54cf5b63SPatrick Mooney 751*54cf5b63SPatrick Mooney return (true); 752*54cf5b63SPatrick Mooney } 753