]> git.proxmox.com Git - mirror_qemu.git/blame - target/i386/hvf/x86_cpuid.c
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
[mirror_qemu.git] / target / i386 / hvf / x86_cpuid.c
CommitLineData
db5cb9a0
SAGDR
1/*
2 * i386 CPUID helper functions
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2017 Google Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
8af82b8e 10 * version 2.1 of the License, or (at your option) any later version.
db5cb9a0
SAGDR
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * cpuid
21 */
22
23#include "qemu/osdep.h"
ff2de166 24#include "cpu.h"
db5cb9a0
SAGDR
25#include "x86.h"
26#include "vmx.h"
27#include "sysemu/hvf.h"
28
118f2aad 29static bool xgetbv(uint32_t cpuid_ecx, uint32_t idx, uint64_t *xcr)
db5cb9a0 30{
118f2aad 31 uint32_t xcrl, xcrh;
db5cb9a0 32
118f2aad
HM
33 if (cpuid_ecx & CPUID_EXT_OSXSAVE) {
34 /*
35 * The xgetbv instruction is not available to older versions of
36 * the assembler, so we encode the instruction manually.
37 */
38 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl), "=d" (xcrh) : "c" (idx));
db5cb9a0 39
118f2aad
HM
40 *xcr = (((uint64_t)xcrh) << 32) | xcrl;
41 return true;
42 }
43
44 return false;
db5cb9a0
SAGDR
45}
46
db5cb9a0
SAGDR
47uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
48 int reg)
49{
50 uint64_t cap;
51 uint32_t eax, ebx, ecx, edx;
52
53 host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
54
55 switch (func) {
56 case 0:
57 eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd;
58 break;
59 case 1:
60 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
61 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
62 CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
63 CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX |
64 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS;
65 ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
66 CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
67 CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
68 CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_XSAVE |
69 CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
70 ecx |= CPUID_EXT_HYPERVISOR;
71 break;
72 case 6:
73 eax = CPUID_6_EAX_ARAT;
74 ebx = 0;
75 ecx = 0;
76 edx = 0;
77 break;
78 case 7:
79 if (idx == 0) {
80 ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
81 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 |
82 CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 |
83 CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM |
84 CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
85 CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA |
86 CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF |
87 CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD |
88 CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
89 CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
90 CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
c29b48db 91 CPUID_7_0_EBX_INVPCID;
db5cb9a0 92
db5cb9a0
SAGDR
93 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
94 if (!(cap & CPU_BASED2_INVPCID)) {
95 ebx &= ~CPUID_7_0_EBX_INVPCID;
96 }
97
e7694a5e 98 ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
db5cb9a0
SAGDR
99 edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
100 } else {
101 ebx = 0;
102 ecx = 0;
103 edx = 0;
104 }
105 eax = 0;
106 break;
107 case 0xD:
108 if (idx == 0) {
118f2aad
HM
109 uint64_t host_xcr0;
110 if (xgetbv(ecx, 0, &host_xcr0)) {
111 uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK |
112 XSTATE_SSE_MASK | XSTATE_YMM_MASK |
113 XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK |
114 XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK |
115 XSTATE_Hi16_ZMM_MASK);
116 eax &= supp_xcr0;
117 }
db5cb9a0
SAGDR
118 } else if (idx == 1) {
119 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
120 eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
121 if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) {
122 eax &= ~CPUID_XSAVE_XSAVES;
123 }
124 }
125 break;
126 case 0x80000001:
127 /* LM only if HVF in 64-bit mode */
128 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
129 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
130 CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
131 CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX |
132 CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT |
133 CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX;
65baabca
JC
134 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
135 if (!(cap & CPU_BASED2_RDTSCP)) {
136 edx &= ~CPUID_EXT2_RDTSCP;
137 }
db5cb9a0
SAGDR
138 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap);
139 if (!(cap & CPU_BASED_TSC_OFFSET)) {
140 edx &= ~CPUID_EXT2_RDTSCP;
141 }
142 ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG |
143 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE |
144 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
145 CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
146 break;
147 default:
148 return 0;
149 }
150
151 switch (reg) {
152 case R_EAX:
153 return eax;
154 case R_EBX:
155 return ebx;
156 case R_ECX:
157 return ecx;
158 case R_EDX:
159 return edx;
160 default:
161 return 0;
162 }
163}