mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 04:06:46 +00:00 
			
		
		
		
	 e7694a5eae
			
		
	
	
		e7694a5eae
		
	
	
	
	
		
			
			Drop the duplicated definition of cpuid AVX512_VBMI macro and rename it as CPUID_7_0_ECX_AVX512_VBMI. Rename CPUID_7_0_ECX_VBMI2 as CPUID_7_0_ECX_AVX512_VBMI2. Acked-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Tao Xu <tao3.xu@intel.com> Message-Id: <20190926021055.6970-3-tao3.xu@intel.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
		
			
				
	
	
		
			151 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *  i386 CPUID helper functions
 | |
|  *
 | |
|  *  Copyright (c) 2003 Fabrice Bellard
 | |
|  *  Copyright (c) 2017 Google Inc.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
 | |
|  *
 | |
|  * cpuid
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu-common.h"
 | |
| #include "cpu.h"
 | |
| #include "x86.h"
 | |
| #include "vmx.h"
 | |
| #include "sysemu/hvf.h"
 | |
| 
 | |
| static uint64_t xgetbv(uint32_t xcr)
 | |
| {
 | |
|     uint32_t eax, edx;
 | |
| 
 | |
|     __asm__ volatile ("xgetbv"
 | |
|                       : "=a" (eax), "=d" (edx)
 | |
|                       : "c" (xcr));
 | |
| 
 | |
|     return (((uint64_t)edx) << 32) | eax;
 | |
| }
 | |
| 
 | |
| uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
 | |
|                                  int reg)
 | |
| {
 | |
|     uint64_t cap;
 | |
|     uint32_t eax, ebx, ecx, edx;
 | |
| 
 | |
|     host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
 | |
| 
 | |
|     switch (func) {
 | |
|     case 0:
 | |
|         eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd;
 | |
|         break;
 | |
|     case 1:
 | |
|         edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
 | |
|              CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
 | |
|              CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
 | |
|              CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX |
 | |
|              CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS;
 | |
|         ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
 | |
|              CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
 | |
|              CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
 | |
|              CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_XSAVE |
 | |
|              CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
 | |
|         ecx |= CPUID_EXT_HYPERVISOR;
 | |
|         break;
 | |
|     case 6:
 | |
|         eax = CPUID_6_EAX_ARAT;
 | |
|         ebx = 0;
 | |
|         ecx = 0;
 | |
|         edx = 0;
 | |
|         break;
 | |
|     case 7:
 | |
|         if (idx == 0) {
 | |
|             ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
 | |
|                     CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 |
 | |
|                     CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 |
 | |
|                     CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM |
 | |
|                     CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
 | |
|                     CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA |
 | |
|                     CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF |
 | |
|                     CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD |
 | |
|                     CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
 | |
|                     CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
 | |
|                     CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
 | |
|                     CPUID_7_0_EBX_INVPCID;
 | |
| 
 | |
|             hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
 | |
|             if (!(cap & CPU_BASED2_INVPCID)) {
 | |
|                 ebx &= ~CPUID_7_0_EBX_INVPCID;
 | |
|             }
 | |
| 
 | |
|             ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
 | |
|             edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
 | |
|         } else {
 | |
|             ebx = 0;
 | |
|             ecx = 0;
 | |
|             edx = 0;
 | |
|         }
 | |
|         eax = 0;
 | |
|         break;
 | |
|     case 0xD:
 | |
|         if (idx == 0) {
 | |
|             uint64_t host_xcr0 = xgetbv(0);
 | |
|             uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK | XSTATE_SSE_MASK |
 | |
|                                   XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK |
 | |
|                                   XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK |
 | |
|                                   XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK);
 | |
|             eax &= supp_xcr0;
 | |
|         } else if (idx == 1) {
 | |
|             hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
 | |
|             eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
 | |
|             if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) {
 | |
|                 eax &= ~CPUID_XSAVE_XSAVES;
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
|     case 0x80000001:
 | |
|         /* LM only if HVF in 64-bit mode */
 | |
|         edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
 | |
|                 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
 | |
|                 CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
 | |
|                 CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX |
 | |
|                 CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT |
 | |
|                 CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX;
 | |
|         hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap);
 | |
|         if (!(cap & CPU_BASED_TSC_OFFSET)) {
 | |
|             edx &= ~CPUID_EXT2_RDTSCP;
 | |
|         }
 | |
|         ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG |
 | |
|                 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE |
 | |
|                 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
 | |
|                 CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
 | |
|         break;
 | |
|     default:
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     switch (reg) {
 | |
|     case R_EAX:
 | |
|         return eax;
 | |
|     case R_EBX:
 | |
|         return ebx;
 | |
|     case R_ECX:
 | |
|         return ecx;
 | |
|     case R_EDX:
 | |
|         return edx;
 | |
|     default:
 | |
|         return 0;
 | |
|     }
 | |
| }
 |