| /* |
| * i386 CPUID helper functions |
| * |
| * Copyright (c) 2003 Fabrice Bellard |
| * |
| * This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "qemu/units.h" |
| #include "qemu/cutils.h" |
| #include "qemu/bitops.h" |
| #include "qemu/qemu-print.h" |
| |
| #include "cpu.h" |
| #include "exec/exec-all.h" |
| #include "sysemu/kvm.h" |
| #include "sysemu/reset.h" |
| #include "sysemu/hvf.h" |
| #include "sysemu/cpus.h" |
| #include "kvm_i386.h" |
| #include "sev_i386.h" |
| |
| #include "qemu/error-report.h" |
| #include "qemu/module.h" |
| #include "qemu/option.h" |
| #include "qemu/config-file.h" |
| #include "qapi/error.h" |
| #include "qapi/qapi-visit-machine.h" |
| #include "qapi/qapi-visit-run-state.h" |
| #include "qapi/qmp/qdict.h" |
| #include "qapi/qmp/qerror.h" |
| #include "qapi/visitor.h" |
| #include "qom/qom-qobject.h" |
| #include "sysemu/arch_init.h" |
| #include "qapi/qapi-commands-machine-target.h" |
| |
| #include "standard-headers/asm-x86/kvm_para.h" |
| |
| #include "sysemu/sysemu.h" |
| #include "sysemu/tcg.h" |
| #include "hw/qdev-properties.h" |
| #include "hw/i386/topology.h" |
| #ifndef CONFIG_USER_ONLY |
| #include "exec/address-spaces.h" |
| #include "hw/xen/xen.h" |
| #include "hw/i386/apic_internal.h" |
| #include "hw/boards.h" |
| #endif |
| |
| #include "disas/capstone.h" |
| |
| /* Helpers for building CPUID[2] descriptors: */ |
| |
| struct CPUID2CacheDescriptorInfo { |
| enum CacheType type; |
| int level; |
| int size; |
| int line_size; |
| int associativity; |
| }; |
| |
| /* |
| * Known CPUID 2 cache descriptors. |
| * From Intel SDM Volume 2A, CPUID instruction |
| */ |
| struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = { |
| [0x06] = { .level = 1, .type = INSTRUCTION_CACHE, .size = 8 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x08] = { .level = 1, .type = INSTRUCTION_CACHE, .size = 16 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x09] = { .level = 1, .type = INSTRUCTION_CACHE, .size = 32 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x0A] = { .level = 1, .type = DATA_CACHE, .size = 8 * KiB, |
| .associativity = 2, .line_size = 32, }, |
| [0x0C] = { .level = 1, .type = DATA_CACHE, .size = 16 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x0D] = { .level = 1, .type = DATA_CACHE, .size = 16 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x0E] = { .level = 1, .type = DATA_CACHE, .size = 24 * KiB, |
| .associativity = 6, .line_size = 64, }, |
| [0x1D] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB, |
| .associativity = 2, .line_size = 64, }, |
| [0x21] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, |
| .associativity = 8, .line_size = 64, }, |
| /* lines per sector is not supported cpuid2_cache_descriptor(), |
| * so descriptors 0x22, 0x23 are not included |
| */ |
| [0x24] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| /* lines per sector is not supported cpuid2_cache_descriptor(), |
| * so descriptors 0x25, 0x20 are not included |
| */ |
| [0x2C] = { .level = 1, .type = DATA_CACHE, .size = 32 * KiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x30] = { .level = 1, .type = INSTRUCTION_CACHE, .size = 32 * KiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x41] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x42] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x43] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x44] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x45] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 4, .line_size = 32, }, |
| [0x46] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x47] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x48] = { .level = 2, .type = UNIFIED_CACHE, .size = 3 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| /* Descriptor 0x49 depends on CPU family/model, so it is not included */ |
| [0x4A] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| [0x4B] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| [0x4C] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| [0x4D] = { .level = 3, .type = UNIFIED_CACHE, .size = 16 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| [0x4E] = { .level = 2, .type = UNIFIED_CACHE, .size = 6 * MiB, |
| .associativity = 24, .line_size = 64, }, |
| [0x60] = { .level = 1, .type = DATA_CACHE, .size = 16 * KiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x66] = { .level = 1, .type = DATA_CACHE, .size = 8 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x67] = { .level = 1, .type = DATA_CACHE, .size = 16 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x68] = { .level = 1, .type = DATA_CACHE, .size = 32 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x78] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 4, .line_size = 64, }, |
| /* lines per sector is not supported cpuid2_cache_descriptor(), |
| * so descriptors 0x79, 0x7A, 0x7B, 0x7C are not included. |
| */ |
| [0x7D] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x7F] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 2, .line_size = 64, }, |
| [0x80] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 8, .line_size = 64, }, |
| [0x82] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, |
| .associativity = 8, .line_size = 32, }, |
| [0x83] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 8, .line_size = 32, }, |
| [0x84] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 8, .line_size = 32, }, |
| [0x85] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 8, .line_size = 32, }, |
| [0x86] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0x87] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0xD0] = { .level = 3, .type = UNIFIED_CACHE, .size = 512 * KiB, |
| .associativity = 4, .line_size = 64, }, |
| [0xD1] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 4, .line_size = 64, }, |
| [0xD2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 4, .line_size = 64, }, |
| [0xD6] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0xD7] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0xD8] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, |
| .associativity = 8, .line_size = 64, }, |
| [0xDC] = { .level = 3, .type = UNIFIED_CACHE, .size = 1.5 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| [0xDD] = { .level = 3, .type = UNIFIED_CACHE, .size = 3 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| [0xDE] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB, |
| .associativity = 12, .line_size = 64, }, |
| [0xE2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| [0xE3] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| [0xE4] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, |
| .associativity = 16, .line_size = 64, }, |
| [0xEA] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB, |
| .associativity = 24, .line_size = 64, }, |
| [0xEB] = { .level = 3, .type = UNIFIED_CACHE, .size = 18 * MiB, |
| .associativity = 24, .line_size = 64, }, |
| [0xEC] = { .level = 3, .type = UNIFIED_CACHE, .size = 24 * MiB, |
| .associativity = 24, .line_size = 64, }, |
| }; |
| |
| /* |
| * "CPUID leaf 2 does not report cache descriptor information, |
| * use CPUID leaf 4 to query cache parameters" |
| */ |
| #define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF |
| |
| /* |
| * Return a CPUID 2 cache descriptor for a given cache. |
| * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE |
| */ |
| static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache) |
| { |
| int i; |
| |
| assert(cache->size > 0); |
| assert(cache->level > 0); |
| assert(cache->line_size > 0); |
| assert(cache->associativity > 0); |
| for (i = 0; i < ARRAY_SIZE(cpuid2_cache_descriptors); i++) { |
| struct CPUID2CacheDescriptorInfo *d = &cpuid2_cache_descriptors[i]; |
| if (d->level == cache->level && d->type == cache->type && |
| d->size == cache->size && d->line_size == cache->line_size && |
| d->associativity == cache->associativity) { |
| return i; |
| } |
| } |
| |
| return CACHE_DESCRIPTOR_UNAVAILABLE; |
| } |
| |
| /* CPUID Leaf 4 constants: */ |
| |
| /* EAX: */ |
| #define CACHE_TYPE_D 1 |
| #define CACHE_TYPE_I 2 |
| #define CACHE_TYPE_UNIFIED 3 |
| |
| #define CACHE_LEVEL(l) (l << 5) |
| |
| #define CACHE_SELF_INIT_LEVEL (1 << 8) |
| |
| /* EDX: */ |
| #define CACHE_NO_INVD_SHARING (1 << 0) |
| #define CACHE_INCLUSIVE (1 << 1) |
| #define CACHE_COMPLEX_IDX (1 << 2) |
| |
| /* Encode CacheType for CPUID[4].EAX */ |
| #define CACHE_TYPE(t) (((t) == DATA_CACHE) ? CACHE_TYPE_D : \ |
| ((t) == INSTRUCTION_CACHE) ? CACHE_TYPE_I : \ |
| ((t) == UNIFIED_CACHE) ? CACHE_TYPE_UNIFIED : \ |
| 0 /* Invalid value */) |
| |
| |
| /* Encode cache info for CPUID[4] */ |
| static void encode_cache_cpuid4(CPUCacheInfo *cache, |
| int num_apic_ids, int num_cores, |
| uint32_t *eax, uint32_t *ebx, |
| uint32_t *ecx, uint32_t *edx) |
| { |
| assert(cache->size == cache->line_size * cache->associativity * |
| cache->partitions * cache->sets); |
| |
| assert(num_apic_ids > 0); |
| *eax = CACHE_TYPE(cache->type) | |
| CACHE_LEVEL(cache->level) | |
| (cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) | |
| ((num_cores - 1) << 26) | |
| ((num_apic_ids - 1) << 14); |
| |
| assert(cache->line_size > 0); |
| assert(cache->partitions > 0); |
| assert(cache->associativity > 0); |
| /* We don't implement fully-associative caches */ |
| assert(cache->associativity < cache->sets); |
| *ebx = (cache->line_size - 1) | |
| ((cache->partitions - 1) << 12) | |
| ((cache->associativity - 1) << 22); |
| |
| assert(cache->sets > 0); |
| *ecx = cache->sets - 1; |
| |
| *edx = (cache->no_invd_sharing ? CACHE_NO_INVD_SHARING : 0) | |
| (cache->inclusive ? CACHE_INCLUSIVE : 0) | |
| (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0); |
| } |
| |
| /* Encode cache info for CPUID[0x80000005].ECX or CPUID[0x80000005].EDX */ |
| static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache) |
| { |
| assert(cache->size % 1024 == 0); |
| assert(cache->lines_per_tag > 0); |
| assert(cache->associativity > 0); |
| assert(cache->line_size > 0); |
| return ((cache->size / 1024) << 24) | (cache->associativity << 16) | |
| (cache->lines_per_tag << 8) | (cache->line_size); |
| } |
| |
| #define ASSOC_FULL 0xFF |
| |
| /* AMD associativity encoding used on CPUID Leaf 0x80000006: */ |
| #define AMD_ENC_ASSOC(a) (a <= 1 ? a : \ |
| a == 2 ? 0x2 : \ |
| a == 4 ? 0x4 : \ |
| a == 8 ? 0x6 : \ |
| a == 16 ? 0x8 : \ |
| a == 32 ? 0xA : \ |
| a == 48 ? 0xB : \ |
| a == 64 ? 0xC : \ |
| a == 96 ? 0xD : \ |
| a == 128 ? 0xE : \ |
| a == ASSOC_FULL ? 0xF : \ |
| 0 /* invalid value */) |
| |
| /* |
| * Encode cache info for CPUID[0x80000006].ECX and CPUID[0x80000006].EDX |
| * @l3 can be NULL. |
| */ |
| static void encode_cache_cpuid80000006(CPUCacheInfo *l2, |
| CPUCacheInfo *l3, |
| uint32_t *ecx, uint32_t *edx) |
| { |
| assert(l2->size % 1024 == 0); |
| assert(l2->associativity > 0); |
| assert(l2->lines_per_tag > 0); |
| assert(l2->line_size > 0); |
| *ecx = ((l2->size / 1024) << 16) | |
| (AMD_ENC_ASSOC(l2->associativity) << 12) | |
| (l2->lines_per_tag << 8) | (l2->line_size); |
| |
| if (l3) { |
| assert(l3->size % (512 * 1024) == 0); |
| assert(l3->associativity > 0); |
| assert(l3->lines_per_tag > 0); |
| assert(l3->line_size > 0); |
| *edx = ((l3->size / (512 * 1024)) << 18) | |
| (AMD_ENC_ASSOC(l3->associativity) << 12) | |
| (l3->lines_per_tag << 8) | (l3->line_size); |
| } else { |
| *edx = 0; |
| } |
| } |
| |
| /* Encode cache info for CPUID[8000001D] */ |
| static void encode_cache_cpuid8000001d(CPUCacheInfo *cache, |
| X86CPUTopoInfo *topo_info, |
| uint32_t *eax, uint32_t *ebx, |
| uint32_t *ecx, uint32_t *edx) |
| { |
| uint32_t l3_cores; |
| unsigned nodes = MAX(topo_info->nodes_per_pkg, 1); |
| |
| assert(cache->size == cache->line_size * cache->associativity * |
| cache->partitions * cache->sets); |
| |
| *eax = CACHE_TYPE(cache->type) | CACHE_LEVEL(cache->level) | |
| (cache->self_init ? CACHE_SELF_INIT_LEVEL : 0); |
| |
| /* L3 is shared among multiple cores */ |
| if (cache->level == 3) { |
| l3_cores = DIV_ROUND_UP((topo_info->dies_per_pkg * |
| topo_info->cores_per_die * |
| topo_info->threads_per_core), |
| nodes); |
| *eax |= (l3_cores - 1) << 14; |
| } else { |
| *eax |= ((topo_info->threads_per_core - 1) << 14); |
| } |
| |
| assert(cache->line_size > 0); |
| assert(cache->partitions > 0); |
| assert(cache->associativity > 0); |
| /* We don't implement fully-associative caches */ |
| assert(cache->associativity < cache->sets); |
| *ebx = (cache->line_size - 1) | |
| ((cache->partitions - 1) << 12) | |
| ((cache->associativity - 1) << 22); |
| |
| assert(cache->sets > 0); |
| *ecx = cache->sets - 1; |
| |
| *edx = (cache->no_invd_sharing ? CACHE_NO_INVD_SHARING : 0) | |
| (cache->inclusive ? CACHE_INCLUSIVE : 0) | |
| (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0); |
| } |
| |
| /* Encode cache info for CPUID[8000001E] */ |
| static void encode_topo_cpuid8000001e(X86CPUTopoInfo *topo_info, X86CPU *cpu, |
| uint32_t *eax, uint32_t *ebx, |
| uint32_t *ecx, uint32_t *edx) |
| { |
| X86CPUTopoIDs topo_ids = {0}; |
| unsigned long nodes = MAX(topo_info->nodes_per_pkg, 1); |
| int shift; |
| |
| x86_topo_ids_from_apicid_epyc(cpu->apic_id, topo_info, &topo_ids); |
| |
| *eax = cpu->apic_id; |
| /* |
| * CPUID_Fn8000001E_EBX |
| * 31:16 Reserved |
| * 15:8 Threads per core (The number of threads per core is |
| * Threads per core + 1) |
| * 7:0 Core id (see bit decoding below) |
| * SMT: |
| * 4:3 node id |
| * 2 Core complex id |
| * 1:0 Core id |
| * Non SMT: |
| * 5:4 node id |
| * 3 Core complex id |
| * 1:0 Core id |
| */ |
| *ebx = ((topo_info->threads_per_core - 1) << 8) | (topo_ids.node_id << 3) | |
| (topo_ids.core_id); |
| /* |
| * CPUID_Fn8000001E_ECX |
| * 31:11 Reserved |
| * 10:8 Nodes per processor (Nodes per processor is number of nodes + 1) |
| * 7:0 Node id (see bit decoding below) |
| * 2 Socket id |
| * 1:0 Node id |
| */ |
| if (nodes <= 4) { |
| *ecx = ((nodes - 1) << 8) | (topo_ids.pkg_id << 2) | topo_ids.node_id; |
| } else { |
| /* |
| * Node id fix up. Actual hardware supports up to 4 nodes. But with |
| * more than 32 cores, we may end up with more than 4 nodes. |
| * Node id is a combination of socket id and node id. Only requirement |
| * here is that this number should be unique accross the system. |
| * Shift the socket id to accommodate more nodes. We dont expect both |
| * socket id and node id to be big number at the same time. This is not |
| * an ideal config but we need to to support it. Max nodes we can have |
| * is 32 (255/8) with 8 cores per node and 255 max cores. We only need |
| * 5 bits for nodes. Find the left most set bit to represent the total |
| * number of nodes. find_last_bit returns last set bit(0 based). Left |
| * shift(+1) the socket id to represent all the nodes. |
| */ |
| nodes -= 1; |
| shift = find_last_bit(&nodes, 8); |
| *ecx = (nodes << 8) | (topo_ids.pkg_id << (shift + 1)) | |
| topo_ids.node_id; |
| } |
| *edx = 0; |
| } |
| |
| /* |
| * Definitions of the hardcoded cache entries we expose: |
| * These are legacy cache values. If there is a need to change any |
| * of these values please use builtin_x86_defs |
| */ |
| |
| /* L1 data cache: */ |
| static CPUCacheInfo legacy_l1d_cache = { |
| .type = DATA_CACHE, |
| .level = 1, |
| .size = 32 * KiB, |
| .self_init = 1, |
| .line_size = 64, |
| .associativity = 8, |
| .sets = 64, |
| .partitions = 1, |
| .no_invd_sharing = true, |
| }; |
| |
| /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */ |
| static CPUCacheInfo legacy_l1d_cache_amd = { |
| .type = DATA_CACHE, |
| .level = 1, |
| .size = 64 * KiB, |
| .self_init = 1, |
| .line_size = 64, |
| .associativity = 2, |
| .sets = 512, |
| .partitions = 1, |
| .lines_per_tag = 1, |
| .no_invd_sharing = true, |
| }; |
| |
| /* L1 instruction cache: */ |
| static CPUCacheInfo legacy_l1i_cache = { |
| .type = INSTRUCTION_CACHE, |
| .level = 1, |
| .size = 32 * KiB, |
| .self_init = 1, |
| .line_size = 64, |
| .associativity = 8, |
| .sets = 64, |
| .partitions = 1, |
| .no_invd_sharing = true, |
| }; |
| |
| /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */ |
| static CPUCacheInfo legacy_l1i_cache_amd = { |
| .type = INSTRUCTION_CACHE, |
| .level = 1, |
| .size = 64 * KiB, |
| .self_init = 1, |
| .line_size = 64, |
| .associativity = 2, |
| .sets = 512, |
| .partitions = 1, |
| .lines_per_tag = 1, |
| .no_invd_sharing = true, |
| }; |
| |
| /* Level 2 unified cache: */ |
| static CPUCacheInfo legacy_l2_cache = { |
| .type = UNIFIED_CACHE, |
| .level = 2, |
| .size = 4 * MiB, |
| .self_init = 1, |
| .line_size = 64, |
| .associativity = 16, |
| .sets = 4096, |
| .partitions = 1, |
| .no_invd_sharing = true, |
| }; |
| |
| /*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */ |
| static CPUCacheInfo legacy_l2_cache_cpuid2 = { |
| .type = UNIFIED_CACHE, |
| .level = 2, |
| .size = 2 * MiB, |
| .line_size = 64, |
| .associativity = 8, |
| }; |
| |
| |
| /*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */ |
| static CPUCacheInfo legacy_l2_cache_amd = { |
| .type = UNIFIED_CACHE, |
| .level = 2, |
| .size = 512 * KiB, |
| .line_size = 64, |
| .lines_per_tag = 1, |
| .associativity = 16, |
| .sets = 512, |
| .partitions = 1, |
| }; |
| |
| /* Level 3 unified cache: */ |
| static CPUCacheInfo legacy_l3_cache = { |
| .type = UNIFIED_CACHE, |
| .level = 3, |
| .size = 16 * MiB, |
| .line_size = 64, |
| .associativity = 16, |
| .sets = 16384, |
| .partitions = 1, |
| .lines_per_tag = 1, |
| .self_init = true, |
| .inclusive = true, |
| .complex_indexing = true, |
| }; |
| |
| /* TLB definitions: */ |
| |
| #define L1_DTLB_2M_ASSOC 1 |
| #define L1_DTLB_2M_ENTRIES 255 |
| #define L1_DTLB_4K_ASSOC 1 |
| #define L1_DTLB_4K_ENTRIES 255 |
| |
| #define L1_ITLB_2M_ASSOC 1 |
| #define L1_ITLB_2M_ENTRIES 255 |
| #define L1_ITLB_4K_ASSOC 1 |
| #define L1_ITLB_4K_ENTRIES 255 |
| |
| #define L2_DTLB_2M_ASSOC 0 /* disabled */ |
| #define L2_DTLB_2M_ENTRIES 0 /* disabled */ |
| #define L2_DTLB_4K_ASSOC 4 |
| #define L2_DTLB_4K_ENTRIES 512 |
| |
| #define L2_ITLB_2M_ASSOC 0 /* disabled */ |
| #define L2_ITLB_2M_ENTRIES 0 /* disabled */ |
| #define L2_ITLB_4K_ASSOC 4 |
| #define L2_ITLB_4K_ENTRIES 512 |
| |
| /* CPUID Leaf 0x14 constants: */ |
| #define INTEL_PT_MAX_SUBLEAF 0x1 |
| /* |
| * bit[00]: IA32_RTIT_CTL.CR3 filter can be set to 1 and IA32_RTIT_CR3_MATCH |
| * MSR can be accessed; |
| * bit[01]: Support Configurable PSB and Cycle-Accurate Mode; |
| * bit[02]: Support IP Filtering, TraceStop filtering, and preservation |
| * of Intel PT MSRs across warm reset; |
| * bit[03]: Support MTC timing packet and suppression of COFI-based packets; |
| */ |
| #define INTEL_PT_MINIMAL_EBX 0xf |
| /* |
| * bit[00]: Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1 and |
| * IA32_RTIT_OUTPUT_BASE and IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be |
| * accessed; |
| * bit[01]: ToPA tables can hold any number of output entries, up to the |
| * maximum allowed by the MaskOrTableOffset field of |
| * IA32_RTIT_OUTPUT_MASK_PTRS; |
| * bit[02]: Support Single-Range Output scheme; |
| */ |
| #define INTEL_PT_MINIMAL_ECX 0x7 |
| /* generated packets which contain IP payloads have LIP values */ |
| #define INTEL_PT_IP_LIP (1 << 31) |
| #define INTEL_PT_ADDR_RANGES_NUM 0x2 /* Number of configurable address ranges */ |
| #define INTEL_PT_ADDR_RANGES_NUM_MASK 0x3 |
| #define INTEL_PT_MTC_BITMAP (0x0249 << 16) /* Support ART(0,3,6,9) */ |
| #define INTEL_PT_CYCLE_BITMAP 0x1fff /* Support 0,2^(0~11) */ |
| #define INTEL_PT_PSB_BITMAP (0x003f << 16) /* Support 2K,4K,8K,16K,32K,64K */ |
| |
| static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, |
| uint32_t vendor2, uint32_t vendor3) |
| { |
| int i; |
| for (i = 0; i < 4; i++) { |
| dst[i] = vendor1 >> (8 * i); |
| dst[i + 4] = vendor2 >> (8 * i); |
| dst[i + 8] = vendor3 >> (8 * i); |
| } |
| dst[CPUID_VENDOR_SZ] = '\0'; |
| } |
| |
| #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) |
| #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \ |
| CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC) |
| #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \ |
| CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \ |
| CPUID_PSE36 | CPUID_FXSR) |
| #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE) |
| #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \ |
| CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ |
| CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ |
| CPUID_PAE | CPUID_SEP | CPUID_APIC) |
| |
| #define TCG_FEATURES (CPUID_FP87 | 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_ACPI | CPUID_MMX | \ |
| CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_DE) |
| /* partly implemented: |
| CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */ |
| /* missing: |
| CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */ |
| #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \ |
| CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \ |
| CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \ |
| CPUID_EXT_XSAVE | /* CPUID_EXT_OSXSAVE is dynamic */ \ |
| CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR | \ |
| CPUID_EXT_RDRAND) |
| /* missing: |
| CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX, |
| CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA, |
| CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA, |
| CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AVX, |
| CPUID_EXT_F16C */ |
| |
| #ifdef TARGET_X86_64 |
| #define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM) |
| #else |
| #define TCG_EXT2_X86_64_FEATURES 0 |
| #endif |
| |
| #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \ |
| CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ |
| CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \ |
| TCG_EXT2_X86_64_FEATURES) |
| #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ |
| CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) |
| #define TCG_EXT4_FEATURES 0 |
| #define TCG_SVM_FEATURES CPUID_SVM_NPT |
| #define TCG_KVM_FEATURES 0 |
| #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \ |
| CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \ |
| CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \ |
| CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \ |
| CPUID_7_0_EBX_ERMS) |
| /* missing: |
| CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, |
| CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM, |
| CPUID_7_0_EBX_RDSEED */ |
| #define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_PKU | \ |
| /* CPUID_7_0_ECX_OSPKE is dynamic */ \ |
| CPUID_7_0_ECX_LA57) |
| #define TCG_7_0_EDX_FEATURES 0 |
| #define TCG_7_1_EAX_FEATURES 0 |
| #define TCG_APM_FEATURES 0 |
| #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT |
| #define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1) |
| /* missing: |
| CPUID_XSAVE_XSAVEC, CPUID_XSAVE_XSAVES */ |
| |
| typedef enum FeatureWordType { |
| CPUID_FEATURE_WORD, |
| MSR_FEATURE_WORD, |
| } FeatureWordType; |
| |
| typedef struct FeatureWordInfo { |
| FeatureWordType type; |
| /* feature flags names are taken from "Intel Processor Identification and |
| * the CPUID Instruction" and AMD's "CPUID Specification". |
| * In cases of disagreement between feature naming conventions, |
| * aliases may be added. |
| */ |
| const char *feat_names[64]; |
| union { |
| /* If type==CPUID_FEATURE_WORD */ |
| struct { |
| uint32_t eax; /* Input EAX for CPUID */ |
| bool needs_ecx; /* CPUID instruction uses ECX as input */ |
| uint32_t ecx; /* Input ECX value for CPUID */ |
| int reg; /* output register (R_* constant) */ |
| } cpuid; |
| /* If type==MSR_FEATURE_WORD */ |
| struct { |
| uint32_t index; |
| } msr; |
| }; |
| uint64_t tcg_features; /* Feature flags supported by TCG */ |
| uint64_t unmigratable_flags; /* Feature flags known to be unmigratable */ |
| uint64_t migratable_flags; /* Feature flags known to be migratable */ |
| /* Features that shouldn't be auto-enabled by "-cpu host" */ |
| uint64_t no_autoenable_flags; |
| } FeatureWordInfo; |
| |
| static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { |
| [FEAT_1_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "fpu", "vme", "de", "pse", |
| "tsc", "msr", "pae", "mce", |
| "cx8", "apic", NULL, "sep", |
| "mtrr", "pge", "mca", "cmov", |
| "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, |
| NULL, "ds" /* Intel dts */, "acpi", "mmx", |
| "fxsr", "sse", "sse2", "ss", |
| "ht" /* Intel htt */, "tm", "ia64", "pbe", |
| }, |
| .cpuid = {.eax = 1, .reg = R_EDX, }, |
| .tcg_features = TCG_FEATURES, |
| }, |
| [FEAT_1_ECX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "pni" /* Intel,AMD sse3 */, "pclmulqdq", "dtes64", "monitor", |
| "ds-cpl", "vmx", "smx", "est", |
| "tm2", "ssse3", "cid", NULL, |
| "fma", "cx16", "xtpr", "pdcm", |
| NULL, "pcid", "dca", "sse4.1", |
| "sse4.2", "x2apic", "movbe", "popcnt", |
| "tsc-deadline", "aes", "xsave", NULL /* osxsave */, |
| "avx", "f16c", "rdrand", "hypervisor", |
| }, |
| .cpuid = { .eax = 1, .reg = R_ECX, }, |
| .tcg_features = TCG_EXT_FEATURES, |
| }, |
| /* Feature names that are already defined on feature_name[] but |
| * are set on CPUID[8000_0001].EDX on AMD CPUs don't have their |
| * names on feat_names below. They are copied automatically |
| * to features[FEAT_8000_0001_EDX] if and only if CPU vendor is AMD. |
| */ |
| [FEAT_8000_0001_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */, |
| NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */, |
| NULL /* cx8 */, NULL /* apic */, NULL, "syscall", |
| NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */, |
| NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */, |
| "nx", NULL, "mmxext", NULL /* mmx */, |
| NULL /* fxsr */, "fxsr-opt", "pdpe1gb", "rdtscp", |
| NULL, "lm", "3dnowext", "3dnow", |
| }, |
| .cpuid = { .eax = 0x80000001, .reg = R_EDX, }, |
| .tcg_features = TCG_EXT2_FEATURES, |
| }, |
| [FEAT_8000_0001_ECX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "lahf-lm", "cmp-legacy", "svm", "extapic", |
| "cr8legacy", "abm", "sse4a", "misalignsse", |
| "3dnowprefetch", "osvw", "ibs", "xop", |
| "skinit", "wdt", NULL, "lwp", |
| "fma4", "tce", NULL, "nodeid-msr", |
| NULL, "tbm", "topoext", "perfctr-core", |
| "perfctr-nb", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x80000001, .reg = R_ECX, }, |
| .tcg_features = TCG_EXT3_FEATURES, |
| /* |
| * TOPOEXT is always allowed but can't be enabled blindly by |
| * "-cpu host", as it requires consistent cache topology info |
| * to be provided so it doesn't confuse guests. |
| */ |
| .no_autoenable_flags = CPUID_EXT3_TOPOEXT, |
| }, |
| [FEAT_C000_0001_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, "xstore", "xstore-en", |
| NULL, NULL, "xcrypt", "xcrypt-en", |
| "ace2", "ace2-en", "phe", "phe-en", |
| "pmm", "pmm-en", NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0xC0000001, .reg = R_EDX, }, |
| .tcg_features = TCG_EXT4_FEATURES, |
| }, |
| [FEAT_KVM] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", |
| "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", |
| NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", |
| "kvm-poll-control", "kvm-pv-sched-yield", NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| "kvmclock-stable-bit", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EAX, }, |
| .tcg_features = TCG_KVM_FEATURES, |
| }, |
| [FEAT_KVM_HINTS] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "kvm-hint-dedicated", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EDX, }, |
| .tcg_features = TCG_KVM_FEATURES, |
| /* |
| * KVM hints aren't auto-enabled by -cpu host, they need to be |
| * explicitly enabled in the command-line. |
| */ |
| .no_autoenable_flags = ~0U, |
| }, |
| /* |
| * .feat_names are commented out for Hyper-V enlightenments because we |
| * don't want to have two different ways for enabling them on QEMU command |
| * line. Some features (e.g. "hyperv_time", "hyperv_vapic", ...) require |
| * enabling several feature bits simultaneously, exposing these bits |
| * individually may just confuse guests. |
| */ |
| [FEAT_HYPERV_EAX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL /* hv_msr_vp_runtime_access */, NULL /* hv_msr_time_refcount_access */, |
| NULL /* hv_msr_synic_access */, NULL /* hv_msr_stimer_access */, |
| NULL /* hv_msr_apic_access */, NULL /* hv_msr_hypercall_access */, |
| NULL /* hv_vpindex_access */, NULL /* hv_msr_reset_access */, |
| NULL /* hv_msr_stats_access */, NULL /* hv_reftsc_access */, |
| NULL /* hv_msr_idle_access */, NULL /* hv_msr_frequency_access */, |
| NULL /* hv_msr_debug_access */, NULL /* hv_msr_reenlightenment_access */, |
| NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x40000003, .reg = R_EAX, }, |
| }, |
| [FEAT_HYPERV_EBX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL /* hv_create_partitions */, NULL /* hv_access_partition_id */, |
| NULL /* hv_access_memory_pool */, NULL /* hv_adjust_message_buffers */, |
| NULL /* hv_post_messages */, NULL /* hv_signal_events */, |
| NULL /* hv_create_port */, NULL /* hv_connect_port */, |
| NULL /* hv_access_stats */, NULL, NULL, NULL /* hv_debugging */, |
| NULL /* hv_cpu_power_management */, NULL /* hv_configure_profiler */, |
| NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x40000003, .reg = R_EBX, }, |
| }, |
| [FEAT_HYPERV_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL /* hv_mwait */, NULL /* hv_guest_debugging */, |
| NULL /* hv_perf_monitor */, NULL /* hv_cpu_dynamic_part */, |
| NULL /* hv_hypercall_params_xmm */, NULL /* hv_guest_idle_state */, |
| NULL, NULL, |
| NULL, NULL, NULL /* hv_guest_crash_msr */, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x40000003, .reg = R_EDX, }, |
| }, |
| [FEAT_HV_RECOMM_EAX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL /* hv_recommend_pv_as_switch */, |
| NULL /* hv_recommend_pv_tlbflush_local */, |
| NULL /* hv_recommend_pv_tlbflush_remote */, |
| NULL /* hv_recommend_msr_apic_access */, |
| NULL /* hv_recommend_msr_reset */, |
| NULL /* hv_recommend_relaxed_timing */, |
| NULL /* hv_recommend_dma_remapping */, |
| NULL /* hv_recommend_int_remapping */, |
| NULL /* hv_recommend_x2apic_msrs */, |
| NULL /* hv_recommend_autoeoi_deprecation */, |
| NULL /* hv_recommend_pv_ipi */, |
| NULL /* hv_recommend_ex_hypercalls */, |
| NULL /* hv_hypervisor_is_nested */, |
| NULL /* hv_recommend_int_mbec */, |
| NULL /* hv_recommend_evmcs */, |
| NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x40000004, .reg = R_EAX, }, |
| }, |
| [FEAT_HV_NESTED_EAX] = { |
| .type = CPUID_FEATURE_WORD, |
| .cpuid = { .eax = 0x4000000A, .reg = R_EAX, }, |
| }, |
| [FEAT_SVM] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "npt", "lbrv", "svm-lock", "nrip-save", |
| "tsc-scale", "vmcb-clean", "flushbyasid", "decodeassists", |
| NULL, NULL, "pause-filter", NULL, |
| "pfthreshold", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x8000000A, .reg = R_EDX, }, |
| .tcg_features = TCG_SVM_FEATURES, |
| }, |
| [FEAT_7_0_EBX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "fsgsbase", "tsc-adjust", NULL, "bmi1", |
| "hle", "avx2", NULL, "smep", |
| "bmi2", "erms", "invpcid", "rtm", |
| NULL, NULL, "mpx", NULL, |
| "avx512f", "avx512dq", "rdseed", "adx", |
| "smap", "avx512ifma", "pcommit", "clflushopt", |
| "clwb", "intel-pt", "avx512pf", "avx512er", |
| "avx512cd", "sha-ni", "avx512bw", "avx512vl", |
| }, |
| .cpuid = { |
| .eax = 7, |
| .needs_ecx = true, .ecx = 0, |
| .reg = R_EBX, |
| }, |
| .tcg_features = TCG_7_0_EBX_FEATURES, |
| }, |
| [FEAT_7_0_ECX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, "avx512vbmi", "umip", "pku", |
| NULL /* ospke */, "waitpkg", "avx512vbmi2", NULL, |
| "gfni", "vaes", "vpclmulqdq", "avx512vnni", |
| "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, |
| "la57", NULL, NULL, NULL, |
| NULL, NULL, "rdpid", NULL, |
| NULL, "cldemote", NULL, "movdiri", |
| "movdir64b", NULL, NULL, NULL, |
| }, |
| .cpuid = { |
| .eax = 7, |
| .needs_ecx = true, .ecx = 0, |
| .reg = R_ECX, |
| }, |
| .tcg_features = TCG_7_0_ECX_FEATURES, |
| }, |
| [FEAT_7_0_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, "md-clear", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL /* pconfig */, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, "spec-ctrl", "stibp", |
| NULL, "arch-capabilities", "core-capability", "ssbd", |
| }, |
| .cpuid = { |
| .eax = 7, |
| .needs_ecx = true, .ecx = 0, |
| .reg = R_EDX, |
| }, |
| .tcg_features = TCG_7_0_EDX_FEATURES, |
| }, |
| [FEAT_7_1_EAX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, NULL, NULL, |
| NULL, "avx512-bf16", NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { |
| .eax = 7, |
| .needs_ecx = true, .ecx = 1, |
| .reg = R_EAX, |
| }, |
| .tcg_features = TCG_7_1_EAX_FEATURES, |
| }, |
| [FEAT_8000_0007_EDX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| "invtsc", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x80000007, .reg = R_EDX, }, |
| .tcg_features = TCG_APM_FEATURES, |
| .unmigratable_flags = CPUID_APM_INVTSC, |
| }, |
| [FEAT_8000_0008_EBX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "clzero", NULL, "xsaveerptr", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, "wbnoinvd", NULL, NULL, |
| "ibpb", NULL, NULL, "amd-stibp", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| "amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 0x80000008, .reg = R_EBX, }, |
| .tcg_features = 0, |
| .unmigratable_flags = 0, |
| }, |
| [FEAT_XSAVE] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| "xsaveopt", "xsavec", "xgetbv1", "xsaves", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { |
| .eax = 0xd, |
| .needs_ecx = true, .ecx = 1, |
| .reg = R_EAX, |
| }, |
| .tcg_features = TCG_XSAVE_FEATURES, |
| }, |
| [FEAT_6_EAX] = { |
| .type = CPUID_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, "arat", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .cpuid = { .eax = 6, .reg = R_EAX, }, |
| .tcg_features = TCG_6_EAX_FEATURES, |
| }, |
| [FEAT_XSAVE_COMP_LO] = { |
| .type = CPUID_FEATURE_WORD, |
| .cpuid = { |
| .eax = 0xD, |
| .needs_ecx = true, .ecx = 0, |
| .reg = R_EAX, |
| }, |
| .tcg_features = ~0U, |
| .migratable_flags = 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 | |
| XSTATE_PKRU_MASK, |
| }, |
| [FEAT_XSAVE_COMP_HI] = { |
| .type = CPUID_FEATURE_WORD, |
| .cpuid = { |
| .eax = 0xD, |
| .needs_ecx = true, .ecx = 0, |
| .reg = R_EDX, |
| }, |
| .tcg_features = ~0U, |
| }, |
| /*Below are MSR exposed features*/ |
| [FEAT_ARCH_CAPABILITIES] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", |
| "ssb-no", "mds-no", "pschange-mc-no", "tsx-ctrl", |
| "taa-no", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_ARCH_CAPABILITIES, |
| }, |
| }, |
| [FEAT_CORE_CAPABILITY] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, NULL, NULL, |
| NULL, "split-lock-detect", NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_CORE_CAPABILITY, |
| }, |
| }, |
| |
| [FEAT_VMX_PROCBASED_CTLS] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset", |
| NULL, NULL, NULL, "vmx-hlt-exit", |
| NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit", |
| "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit", |
| "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit", |
| "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", "vmx-movdr-exit", |
| "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf", |
| "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-secondary-ctls", |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_TRUE_PROCBASED_CTLS, |
| } |
| }, |
| |
| [FEAT_VMX_SECONDARY_CTLS] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exit", |
| "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrestricted-guest", |
| "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-exit", |
| "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit", |
| "vmx-rdseed-exit", "vmx-pml", NULL, NULL, |
| "vmx-xsaves", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_PROCBASED_CTLS2, |
| } |
| }, |
| |
| [FEAT_VMX_PINBASED_CTLS] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit", |
| NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_TRUE_PINBASED_CTLS, |
| } |
| }, |
| |
| [FEAT_VMX_EXIT_CTLS] = { |
| .type = MSR_FEATURE_WORD, |
| /* |
| * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from |
| * the LM CPUID bit. |
| */ |
| .feat_names = { |
| NULL, NULL, "vmx-exit-nosave-debugctl", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL, |
| "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-intr", |
| NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat", |
| "vmx-exit-save-efer", "vmx-exit-load-efer", |
| "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs", |
| NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_TRUE_EXIT_CTLS, |
| } |
| }, |
| |
| [FEAT_VMX_ENTRY_CTLS] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, "vmx-entry-noload-debugctl", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, "vmx-entry-ia32e-mode", NULL, NULL, |
| NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer", |
| "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_TRUE_ENTRY_CTLS, |
| } |
| }, |
| |
| [FEAT_VMX_MISC] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| NULL, NULL, NULL, NULL, |
| NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutdown", |
| "vmx-activity-wait-sipi", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_MISC, |
| } |
| }, |
| |
| [FEAT_VMX_EPT_VPID_CAPS] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| "vmx-ept-execonly", NULL, NULL, NULL, |
| NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL, |
| "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL, |
| NULL, "vmx-invept-single-context", "vmx-invept-all-context", NULL, |
| NULL, NULL, NULL, NULL, |
| "vmx-invvpid", NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| "vmx-invvpid-single-addr", "vmx-invept-single-context", |
| "vmx-invvpid-all-context", "vmx-invept-single-context-noglobals", |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| NULL, NULL, NULL, NULL, |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_EPT_VPID_CAP, |
| } |
| }, |
| |
| [FEAT_VMX_BASIC] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| [54] = "vmx-ins-outs", |
| [55] = "vmx-true-ctls", |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_BASIC, |
| }, |
| /* Just to be safe - we don't support setting the MSEG version field. */ |
| .no_autoenable_flags = MSR_VMX_BASIC_DUAL_MONITOR, |
| }, |
| |
| [FEAT_VMX_VMFUNC] = { |
| .type = MSR_FEATURE_WORD, |
| .feat_names = { |
| [0] = "vmx-eptp-switching", |
| }, |
| .msr = { |
| .index = MSR_IA32_VMX_VMFUNC, |
| } |
| }, |
| |
| }; |
| |
| typedef struct FeatureMask { |
| FeatureWord index; |
| uint64_t mask; |
| } FeatureMask; |
| |
| typedef struct FeatureDep { |
| FeatureMask from, to; |
| } FeatureDep; |
| |
| static FeatureDep feature_dependencies[] = { |
| { |
| .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, |
| .to = { FEAT_ARCH_CAPABILITIES, ~0ull }, |
| }, |
| { |
| .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, |
| .to = { FEAT_CORE_CAPABILITY, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_PINBASED_CTLS, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_EXIT_CTLS, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_ENTRY_CTLS, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_MISC, ~0ull }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_VMX }, |
| .to = { FEAT_VMX_BASIC, ~0ull }, |
| }, |
| { |
| .from = { FEAT_8000_0001_EDX, CPUID_EXT2_LM }, |
| .to = { FEAT_VMX_ENTRY_CTLS, VMX_VM_ENTRY_IA32E_MODE }, |
| }, |
| { |
| .from = { FEAT_VMX_PROCBASED_CTLS, VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, ~0ull }, |
| }, |
| { |
| .from = { FEAT_XSAVE, CPUID_XSAVE_XSAVES }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_XSAVES }, |
| }, |
| { |
| .from = { FEAT_1_ECX, CPUID_EXT_RDRAND }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDRAND_EXITING }, |
| }, |
| { |
| .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_INVPCID }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_INVPCID }, |
| }, |
| { |
| .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_RDSEED }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDSEED_EXITING }, |
| }, |
| { |
| .from = { FEAT_8000_0001_EDX, CPUID_EXT2_RDTSCP }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDTSCP }, |
| }, |
| { |
| .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, |
| .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull }, |
| }, |
| { |
| .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, |
| .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST }, |
| }, |
| { |
| .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VPID }, |
| .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull << 32 }, |
| }, |
| { |
| .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VMFUNC }, |
| .to = { FEAT_VMX_VMFUNC, ~0ull }, |
| }, |
| }; |
| |
| typedef struct X86RegisterInfo32 { |
| /* Name of register */ |
| const char *name; |
| /* QAPI enum value register */ |
| X86CPURegister32 qapi_enum; |
| } X86RegisterInfo32; |
| |
| #define REGISTER(reg) \ |
| [R_##reg] = { .name = #reg, .qapi_enum = X86_CPU_REGISTER32_##reg } |
| static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { |
| REGISTER(EAX), |
| REGISTER(ECX), |
| REGISTER(EDX), |
| REGISTER(EBX), |
| REGISTER(ESP), |
| REGISTER(EBP), |
| REGISTER(ESI), |
| REGISTER(EDI), |
| }; |
| #undef REGISTER |
| |
| typedef struct ExtSaveArea { |
| uint32_t feature, bits; |
| uint32_t offset, size; |
| } ExtSaveArea; |
| |
| static const ExtSaveArea x86_ext_save_areas[] = { |
| [XSTATE_FP_BIT] = { |
| /* x87 FP state component is always enabled if XSAVE is supported */ |
| .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE, |
| /* x87 state is in the legacy region of the XSAVE area */ |
| .offset = 0, |
| .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader), |
| }, |
| [XSTATE_SSE_BIT] = { |
| /* SSE state component is always enabled if XSAVE is supported */ |
| .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE, |
| /* SSE state is in the legacy region of the XSAVE area */ |
| .offset = 0, |
| .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader), |
| }, |
| [XSTATE_YMM_BIT] = |
| { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, |
| .offset = offsetof(X86XSaveArea, avx_state), |
| .size = sizeof(XSaveAVX) }, |
| [XSTATE_BNDREGS_BIT] = |
| { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, |
| .offset = offsetof(X86XSaveArea, bndreg_state), |
| .size = sizeof(XSaveBNDREG) }, |
| [XSTATE_BNDCSR_BIT] = |
| { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, |
| .offset = offsetof(X86XSaveArea, bndcsr_state), |
| .size = sizeof(XSaveBNDCSR) }, |
| [XSTATE_OPMASK_BIT] = |
| { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, |
| .offset = offsetof(X86XSaveArea, opmask_state), |
| .size = sizeof(XSaveOpmask) }, |
| [XSTATE_ZMM_Hi256_BIT] = |
| { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, |
| .offset = offsetof(X86XSaveArea, zmm_hi256_state), |
| .size = sizeof(XSaveZMM_Hi256) }, |
| [XSTATE_Hi16_ZMM_BIT] = |
| { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, |
| .offset = offsetof(X86XSaveArea, hi16_zmm_state), |
| .size = sizeof(XSaveHi16_ZMM) }, |
| [XSTATE_PKRU_BIT] = |
| { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, |
| .offset = offsetof(X86XSaveArea, pkru_state), |
| .size = sizeof(XSavePKRU) }, |
| }; |
| |
| static uint32_t xsave_area_size(uint64_t mask) |
| { |
| int i; |
| uint64_t ret = 0; |
| |
| for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) { |
| const ExtSaveArea *esa = &x86_ext_save_areas[i]; |
| if ((mask >> i) & 1) { |
| ret = MAX(ret, esa->offset + esa->size); |
| } |
| } |
| return ret; |
| } |
| |
| static inline bool accel_uses_host_cpuid(void) |
| { |
| return kvm_enabled() || hvf_enabled(); |
| } |
| |
| static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu) |
| { |
| return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 | |
| cpu->env.features[FEAT_XSAVE_COMP_LO]; |
| } |
| |
| const char *get_register_name_32(unsigned int reg) |
| { |
| if (reg >= CPU_NB_REGS32) { |
| return NULL; |
| } |
| return x86_reg_info_32[reg].name; |
| } |
| |
| /* |
| * Returns the set of feature flags that are supported and migratable by |
| * QEMU, for a given FeatureWord. |
| */ |
| static uint64_t x86_cpu_get_migratable_flags(FeatureWord w) |
| { |
| FeatureWordInfo *wi = &feature_word_info[w]; |
| uint64_t r = 0; |
| int i; |
| |
| for (i = 0; i < 64; i++) { |
| uint64_t f = 1ULL << i; |
| |
| /* If the feature name is known, it is implicitly considered migratable, |
| * unless it is explicitly set in unmigratable_flags */ |
| if ((wi->migratable_flags & f) || |
| (wi->feat_names[i] && !(wi->unmigratable_flags & f))) { |
| r |= f; |
| } |
| } |
| return r; |
| } |
| |
| void host_cpuid(uint32_t function, uint32_t count, |
| uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) |
| { |
| uint32_t vec[4]; |
| |
| #ifdef __x86_64__ |
| asm volatile("cpuid" |
| : "=a"(vec[0]), "=b"(vec[1]), |
| "=c"(vec[2]), "=d"(vec[3]) |
| : "0"(function), "c"(count) : "cc"); |
| #elif defined(__i386__) |
| asm volatile("pusha \n\t" |
| "cpuid \n\t" |
| "mov %%eax, 0(%2) \n\t" |
| "mov %%ebx, 4(%2) \n\t" |
| "mov %%ecx, 8(%2) \n\t" |
| "mov %%edx, 12(%2) \n\t" |
| "popa" |
| : : "a"(function), "c"(count), "S"(vec) |
| : "memory", "cc"); |
| #else |
| abort(); |
| #endif |
| |
| if (eax) |
| *eax = vec[0]; |
| if (ebx) |
| *ebx = vec[1]; |
| if (ecx) |
| *ecx = vec[2]; |
| if (edx) |
| *edx = vec[3]; |
| } |
| |
| void host_vendor_fms(char *vendor, int *family, int *model, int *stepping) |
| { |
| uint32_t eax, ebx, ecx, edx; |
| |
| host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); |
| x86_cpu_vendor_words2str(vendor, ebx, edx, ecx); |
| |
| host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); |
| if (family) { |
| *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); |
| } |
| if (model) { |
| *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); |
| } |
| if (stepping) { |
| *stepping = eax & 0x0F; |
| } |
| } |
| |
| /* CPU class name definitions: */ |
| |
| /* Return type name for a given CPU model name |
| * Caller is responsible for freeing the returned string. |
| */ |
| static char *x86_cpu_type_name(const char *model_name) |
| { |
| return g_strdup_printf(X86_CPU_TYPE_NAME("%s"), model_name); |
| } |
| |
| static ObjectClass *x86_cpu_class_by_name(const char *cpu_model) |
| { |
| g_autofree char *typename = x86_cpu_type_name(cpu_model); |
| return object_class_by_name(typename); |
| } |
| |
| static char *x86_cpu_class_get_model_name(X86CPUClass *cc) |
| { |
| const char *class_name = object_class_get_name(OBJECT_CLASS(cc)); |
| assert(g_str_has_suffix(class_name, X86_CPU_TYPE_SUFFIX)); |
| return g_strndup(class_name, |
| strlen(class_name) - strlen(X86_CPU_TYPE_SUFFIX)); |
| } |
| |
| typedef struct PropValue { |
| const char *prop, *value; |
| } PropValue; |
| |
| typedef struct X86CPUVersionDefinition { |
| X86CPUVersion version; |
| const char *alias; |
| const char *note; |
| PropValue *props; |
| } X86CPUVersionDefinition; |
| |
| /* Base definition for a CPU model */ |
| typedef struct X86CPUDefinition { |
| const char *name; |
| uint32_t level; |
| uint32_t xlevel; |
| /* vendor is zero-terminated, 12 character ASCII string */ |
| char vendor[CPUID_VENDOR_SZ + 1]; |
| int family; |
| int model; |
| int stepping; |
| FeatureWordArray features; |
| const char *model_id; |
| CPUCaches *cache_info; |
| |
| /* Use AMD EPYC encoding for apic id */ |
| bool use_epyc_apic_id_encoding; |
| |
| /* |
| * Definitions for alternative versions of CPU model. |
| * List is terminated by item with version == 0. |
| * If NULL, version 1 will be registered automatically. |
| */ |
| const X86CPUVersionDefinition *versions; |
| } X86CPUDefinition; |
| |
| /* Reference to a specific CPU model version */ |
| struct X86CPUModel { |
| /* Base CPU definition */ |
| X86CPUDefinition *cpudef; |
| /* CPU model version */ |
| X86CPUVersion version; |
| const char *note; |
| /* |
| * If true, this is an alias CPU model. |
| * This matters only for "-cpu help" and query-cpu-definitions |
| */ |
| bool is_alias; |
| }; |
| |
| /* Get full model name for CPU version */ |
| static char *x86_cpu_versioned_model_name(X86CPUDefinition *cpudef, |
| X86CPUVersion version) |
| { |
| assert(version > 0); |
| return g_strdup_printf("%s-v%d", cpudef->name, (int)version); |
| } |
| |
| static const X86CPUVersionDefinition *x86_cpu_def_get_versions(X86CPUDefinition *def) |
| { |
| /* When X86CPUDefinition::versions is NULL, we register only v1 */ |
| static const X86CPUVersionDefinition default_version_list[] = { |
| { 1 }, |
| { /* end of list */ } |
| }; |
| |
| return def->versions ?: default_version_list; |
| } |
| |
| bool cpu_x86_use_epyc_apic_id_encoding(const char *cpu_type) |
| { |
| X86CPUClass *xcc = X86_CPU_CLASS(object_class_by_name(cpu_type)); |
| |
| assert(xcc); |
| if (xcc->model && xcc->model->cpudef) { |
| return xcc->model->cpudef->use_epyc_apic_id_encoding; |
| } else { |
| return false; |
| } |
| } |
| |
| static CPUCaches epyc_cache_info = { |
| .l1d_cache = &(CPUCacheInfo) { |
| .type = DATA_CACHE, |
| .level = 1, |
| .size = 32 * KiB, |
| .line_size = 64, |
| .associativity = 8, |
| .partitions = 1, |
| .sets = 64, |
| .lines_per_tag = 1, |
| .self_init = 1, |
| .no_invd_sharing = true, |
| }, |
| .l1i_cache = &(CPUCacheInfo) { |
| .type = INSTRUCTION_CACHE, |
| .level = 1, |
| .size = 64 * KiB, |
| .line_size = 64, |
| .associativity = 4, |
| .partitions = 1, |
| .sets = 256, |
| .lines_per_tag = 1, |
| .self_init = 1, |
| .no_invd_sharing = true, |
| }, |
| .l2_cache = &(CPUCacheInfo) { |
| .type = UNIFIED_CACHE, |
| .level = 2, |
| .size = 512 * KiB, |
| .line_size = 64, |
| .associativity = 8, |
| .partitions = 1, |
| .sets = 1024, |
| .lines_per_tag = 1, |
| }, |
| .l3_cache = &(CPUCacheInfo) { |
| .type = UNIFIED_CACHE, |
| .level = 3, |
| .size = 8 * MiB, |
| .line_size = 64, |
| .associativity = 16, |
| .partitions = 1, |
| .sets = 8192, |
| .lines_per_tag = 1, |
| .self_init = true, |
| .inclusive = true, |
| .complex_indexing = true, |
| }, |
| }; |
| |
| static CPUCaches epyc_rome_cache_info = { |
| .l1d_cache = &(CPUCacheInfo) { |
| .type = DATA_CACHE, |
| .level = 1, |
| .size = 32 * KiB, |
| .line_size = 64, |
| .associativity = 8, |
| .partitions = 1, |
| .sets = 64, |
| .lines_per_tag = 1, |
| .self_init = 1, |
| .no_invd_sharing = true, |
| }, |
| .l1i_cache = &(CPUCacheInfo) { |
| .type = INSTRUCTION_CACHE, |
| .level = 1, |
| .size = 32 * KiB, |
| .line_size = 64, |
| .associativity = 8, |
| .partitions = 1, |
| .sets = 64, |
| .lines_per_tag = 1, |
| .self_init = 1, |
| .no_invd_sharing = true, |
| }, |
| .l2_cache = &(CPUCacheInfo) { |
| .type = UNIFIED_CACHE, |
| .level = 2, |
| .size = 512 * KiB, |
| .line_size = 64, |
| .associativity = 8, |
| .partitions = 1, |
| .sets = 1024, |
| .lines_per_tag = 1, |
| }, |
| .l3_cache = &(CPUCacheInfo) { |
| .type = UNIFIED_CACHE, |
| .level = 3, |
| .size = 16 * MiB, |
| .line_size = 64, |
| .associativity = 16, |
| .partitions = 1, |
| .sets = 16384, |
| .lines_per_tag = 1, |
| .self_init = true, |
| .inclusive = true, |
| .complex_indexing = true, |
| }, |
| }; |
| |
| /* The following VMX features are not supported by KVM and are left out in the |
| * CPU definitions: |
| * |
| * Dual-monitor support (all processors) |
| * Entry to SMM |
| * Deactivate dual-monitor treatment |
| * Number of CR3-target values |
| * Shutdown activity state |
| * Wait-for-SIPI activity state |
| * PAUSE-loop exiting (Westmere and newer) |
| * EPT-violation #VE (Broadwell and newer) |
| * Inject event with insn length=0 (Skylake and newer) |
| * Conceal non-root operation from PT |
| * Conceal VM exits from PT |
| * Conceal VM entries from PT |
| * Enable ENCLS exiting |
| * Mode-based execute control (XS/XU) |
| s TSC scaling (Skylake Server and newer) |
| * GPA translation for PT (IceLake and newer) |
| * User wait and pause |
| * ENCLV exiting |
| * Load IA32_RTIT_CTL |
| * Clear IA32_RTIT_CTL |
| * Advanced VM-exit information for EPT violations |
| * Sub-page write permissions |
| * PT in VMX operation |
| */ |
| |
| static X86CPUDefinition builtin_x86_defs[] = { |
| { |
| .name = "qemu64", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_AMD, |
| .family = 6, |
| .model = 6, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | |
| CPUID_PSE36, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_CX16, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM, |
| .xlevel = 0x8000000A, |
| .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, |
| }, |
| { |
| .name = "phenom", |
| .level = 5, |
| .vendor = CPUID_VENDOR_AMD, |
| .family = 16, |
| .model = 2, |
| .stepping = 3, |
| /* Missing: CPUID_HT */ |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | |
| CPUID_PSE36 | CPUID_VME, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | |
| CPUID_EXT_POPCNT, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | |
| CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT | |
| CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP, |
| /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, |
| CPUID_EXT3_CR8LEG, |
| CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, |
| CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | |
| CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, |
| /* Missing: CPUID_SVM_LBRV */ |
| .features[FEAT_SVM] = |
| CPUID_SVM_NPT, |
| .xlevel = 0x8000001A, |
| .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" |
| }, |
| { |
| .name = "core2duo", |
| .level = 10, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 15, |
| .stepping = 11, |
| /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */ |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | |
| CPUID_PSE36 | CPUID_VME | CPUID_ACPI | CPUID_SS, |
| /* Missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_EST, |
| * CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_VMX */ |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | |
| CPUID_EXT_CX16, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, |
| .xlevel = 0x80000008, |
| .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", |
| }, |
| { |
| .name = "kvm64", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 15, |
| .model = 6, |
| .stepping = 1, |
| /* Missing: CPUID_HT */ |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | CPUID_VME | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | |
| CPUID_PSE36, |
| /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_CX16, |
| /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, |
| /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, |
| CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, |
| CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, |
| CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ |
| .features[FEAT_8000_0001_ECX] = |
| 0, |
| /* VMX features from Cedar Mill/Prescott */ |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING, |
| .xlevel = 0x80000008, |
| .model_id = "Common KVM processor" |
| }, |
| { |
| .name = "qemu32", |
| .level = 4, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 6, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3, |
| .xlevel = 0x80000004, |
| .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, |
| }, |
| { |
| .name = "kvm32", |
| .level = 5, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 15, |
| .model = 6, |
| .stepping = 1, |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | CPUID_VME | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_ECX] = |
| 0, |
| /* VMX features from Yonah */ |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | |
| VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | |
| VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, |
| .xlevel = 0x80000008, |
| .model_id = "Common 32-bit KVM processor" |
| }, |
| { |
| .name = "coreduo", |
| .level = 10, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 14, |
| .stepping = 8, |
| /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */ |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | CPUID_VME | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_ACPI | |
| CPUID_SS, |
| /* Missing: CPUID_EXT_EST, CPUID_EXT_TM2 , CPUID_EXT_XTPR, |
| * CPUID_EXT_PDCM, CPUID_EXT_VMX */ |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_NX, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | |
| VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | |
| VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, |
| .xlevel = 0x80000008, |
| .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", |
| }, |
| { |
| .name = "486", |
| .level = 1, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 4, |
| .model = 8, |
| .stepping = 0, |
| .features[FEAT_1_EDX] = |
| I486_FEATURES, |
| .xlevel = 0, |
| .model_id = "", |
| }, |
| { |
| .name = "pentium", |
| .level = 1, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 5, |
| .model = 4, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| PENTIUM_FEATURES, |
| .xlevel = 0, |
| .model_id = "", |
| }, |
| { |
| .name = "pentium2", |
| .level = 2, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 5, |
| .stepping = 2, |
| .features[FEAT_1_EDX] = |
| PENTIUM2_FEATURES, |
| .xlevel = 0, |
| .model_id = "", |
| }, |
| { |
| .name = "pentium3", |
| .level = 3, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 7, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| PENTIUM3_FEATURES, |
| .xlevel = 0, |
| .model_id = "", |
| }, |
| { |
| .name = "athlon", |
| .level = 2, |
| .vendor = CPUID_VENDOR_AMD, |
| .family = 6, |
| .model = 2, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | |
| CPUID_MCA, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, |
| .xlevel = 0x80000008, |
| .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, |
| }, |
| { |
| .name = "n270", |
| .level = 10, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 28, |
| .stepping = 2, |
| /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */ |
| .features[FEAT_1_EDX] = |
| PPRO_FEATURES | |
| CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | |
| CPUID_ACPI | CPUID_SS, |
| /* Some CPUs got no CPUID_SEP */ |
| /* Missing: CPUID_EXT_DSCPL, CPUID_EXT_EST, CPUID_EXT_TM2, |
| * CPUID_EXT_XTPR */ |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | |
| CPUID_EXT_MOVBE, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_NX, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .xlevel = 0x80000008, |
| .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", |
| }, |
| { |
| .name = "Conroe", |
| .level = 10, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 15, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", |
| }, |
| { |
| .name = "Penryn", |
| .level = 10, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 23, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | |
| CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, |
| .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", |
| }, |
| { |
| .name = "Nehalem", |
| .level = 11, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 26, |
| .stepping = 3, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | |
| CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | |
| MSR_VMX_BASIC_TRUE_CTLS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | |
| VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, |
| .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | |
| MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | |
| MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | |
| MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, |
| .features[FEAT_VMX_EXIT_CTLS] = |
| VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | |
| VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | |
| VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | |
| VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | |
| VMX_PIN_BASED_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | |
| VMX_CPU_BASED_MONITOR_TRAP_FLAG | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | |
| VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | |
| VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | |
| VMX_SECONDARY_EXEC_ENABLE_VPID, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", |
| .versions = (X86CPUVersionDefinition[]) { |
| { .version = 1 }, |
| { |
| .version = 2, |
| .alias = "Nehalem-IBRS", |
| .props = (PropValue[]) { |
| { "spec-ctrl", "on" }, |
| { "model-id", |
| "Intel Core i7 9xx (Nehalem Core i7, IBRS update)" }, |
| { /* end of list */ } |
| } |
| }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .name = "Westmere", |
| .level = 11, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 44, |
| .stepping = 1, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | |
| CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | |
| CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_6_EAX] = |
| CPUID_6_EAX_ARAT, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | |
| MSR_VMX_BASIC_TRUE_CTLS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | |
| VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, |
| .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | |
| MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | |
| MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | |
| MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, |
| .features[FEAT_VMX_EXIT_CTLS] = |
| VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | |
| VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | |
| VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | |
| VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | |
| MSR_VMX_MISC_STORE_LMA, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | |
| VMX_PIN_BASED_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | |
| VMX_CPU_BASED_MONITOR_TRAP_FLAG | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | |
| VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | |
| VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | |
| VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, |
| .xlevel = 0x80000008, |
| .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", |
| .versions = (X86CPUVersionDefinition[]) { |
| { .version = 1 }, |
| { |
| .version = 2, |
| .alias = "Westmere-IBRS", |
| .props = (PropValue[]) { |
| { "spec-ctrl", "on" }, |
| { "model-id", |
| "Westmere E56xx/L56xx/X56xx (IBRS update)" }, |
| { /* end of list */ } |
| } |
| }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .name = "SandyBridge", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 42, |
| .stepping = 1, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | |
| CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | |
| CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | |
| CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | |
| CPUID_EXT_SSE3, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | |
| CPUID_EXT2_SYSCALL, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_XSAVE] = |
| CPUID_XSAVE_XSAVEOPT, |
| .features[FEAT_6_EAX] = |
| CPUID_6_EAX_ARAT, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | |
| MSR_VMX_BASIC_TRUE_CTLS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | |
| VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, |
| .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | |
| MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | |
| MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | |
| MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, |
| .features[FEAT_VMX_EXIT_CTLS] = |
| VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | |
| VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | |
| VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | |
| VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | |
| MSR_VMX_MISC_STORE_LMA, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | |
| VMX_PIN_BASED_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | |
| VMX_CPU_BASED_MONITOR_TRAP_FLAG | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | |
| VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | |
| VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | |
| VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Xeon E312xx (Sandy Bridge)", |
| .versions = (X86CPUVersionDefinition[]) { |
| { .version = 1 }, |
| { |
| .version = 2, |
| .alias = "SandyBridge-IBRS", |
| .props = (PropValue[]) { |
| { "spec-ctrl", "on" }, |
| { "model-id", |
| "Intel Xeon E312xx (Sandy Bridge, IBRS update)" }, |
| { /* end of list */ } |
| } |
| }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .name = "IvyBridge", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 58, |
| .stepping = 9, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | |
| CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | |
| CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | |
| CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | |
| CPUID_EXT_SSE3 | CPUID_EXT_F16C | CPUID_EXT_RDRAND, |
| .features[FEAT_7_0_EBX] = |
| CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_SMEP | |
| CPUID_7_0_EBX_ERMS, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | |
| CPUID_EXT2_SYSCALL, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_LAHF_LM, |
| .features[FEAT_XSAVE] = |
| CPUID_XSAVE_XSAVEOPT, |
| .features[FEAT_6_EAX] = |
| CPUID_6_EAX_ARAT, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | |
| MSR_VMX_BASIC_TRUE_CTLS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | |
| VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, |
| .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | |
| MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | |
| MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | |
| MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, |
| .features[FEAT_VMX_EXIT_CTLS] = |
| VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | |
| VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | |
| VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | |
| VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | |
| MSR_VMX_MISC_STORE_LMA, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | |
| VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | |
| VMX_CPU_BASED_MONITOR_TRAP_FLAG | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | |
| VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | |
| VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | |
| VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | |
| VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | |
| VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | |
| VMX_SECONDARY_EXEC_RDRAND_EXITING, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)", |
| .versions = (X86CPUVersionDefinition[]) { |
| { .version = 1 }, |
| { |
| .version = 2, |
| .alias = "IvyBridge-IBRS", |
| .props = (PropValue[]) { |
| { "spec-ctrl", "on" }, |
| { "model-id", |
| "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)" }, |
| { /* end of list */ } |
| } |
| }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .name = "Haswell", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 60, |
| .stepping = 4, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | |
| CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | |
| CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | |
| CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | |
| CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | |
| CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, |
| .features[FEAT_8000_0001_EDX] = |
| CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | |
| CPUID_EXT2_SYSCALL, |
| .features[FEAT_8000_0001_ECX] = |
| CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, |
| .features[FEAT_7_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_INVPCID | |
| CPUID_7_0_EBX_RTM, |
| .features[FEAT_XSAVE] = |
| CPUID_XSAVE_XSAVEOPT, |
| .features[FEAT_6_EAX] = |
| CPUID_6_EAX_ARAT, |
| .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | |
| MSR_VMX_BASIC_TRUE_CTLS, |
| .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | |
| VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | |
| VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, |
| .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | |
| MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | |
| MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | |
| MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | |
| MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, |
| .features[FEAT_VMX_EXIT_CTLS] = |
| VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | |
| VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | |
| VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | |
| VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | |
| VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, |
| .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | |
| MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, |
| .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | |
| VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | |
| VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, |
| .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | |
| VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | |
| VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | |
| VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | |
| VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | |
| VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | |
| VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | |
| VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | |
| VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | |
| VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | |
| VMX_CPU_BASED_MONITOR_TRAP_FLAG | |
| VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, |
| .features[FEAT_VMX_SECONDARY_CTLS] = |
| VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
| VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | |
| VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | |
| VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | |
| VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | |
| VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | |
| VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | |
| VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | |
| VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, |
| .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, |
| .xlevel = 0x80000008, |
| .model_id = "Intel Core Processor (Haswell)", |
| .versions = (X86CPUVersionDefinition[]) { |
| { .version = 1 }, |
| { |
| .version = 2, |
| .alias = "Haswell-noTSX", |
| .props = (PropValue[]) { |
| { "hle", "off" }, |
| { "rtm", "off" }, |
| { "stepping", "1" }, |
| { "model-id", "Intel Core Processor (Haswell, no TSX)", }, |
| { /* end of list */ } |
| }, |
| }, |
| { |
| .version = 3, |
| .alias = "Haswell-IBRS", |
| .props = (PropValue[]) { |
| /* Restore TSX features removed by -v2 above */ |
| { "hle", "on" }, |
| { "rtm", "on" }, |
| /* |
| * Haswell and Haswell-IBRS had stepping=4 in |
| * QEMU 4.0 and older |
| */ |
| { "stepping", "4" }, |
| { "spec-ctrl", "on" }, |
| { "model-id", |
| "Intel Core Processor (Haswell, IBRS)" }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .version = 4, |
| .alias = "Haswell-noTSX-IBRS", |
| .props = (PropValue[]) { |
| { "hle", "off" }, |
| { "rtm", "off" }, |
| /* spec-ctrl was already enabled by -v3 above */ |
| { "stepping", "1" }, |
| { "model-id", |
| "Intel Core Processor (Haswell, no TSX, IBRS)" }, |
| { /* end of list */ } |
| } |
| }, |
| { /* end of list */ } |
| } |
| }, |
| { |
| .name = "Broadwell", |
| .level = 0xd, |
| .vendor = CPUID_VENDOR_INTEL, |
| .family = 6, |
| .model = 61, |
| .stepping = 2, |
| .features[FEAT_1_EDX] = |
| CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | |
| CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | |
| CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | |
| CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | |
| CPUID_DE | CPUID_FP87, |
| .features[FEAT_1_ECX] = |
| CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | |
| CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | |
| CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | |
| CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | |
|