aboutsummaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2016-10-11 08:56:52 +0200
committerThomas Huth <thuth@redhat.com>2016-12-20 21:52:12 +0100
commitfcf5ef2ab52c621a4617ebbef36bf43b4003f4c0 (patch)
tree2b450d96b01455df8ed908bf8f26ddc388a03380 /target-i386
parent82ecffa8c050bf5bbc13329e9b65eac1caa5b55c (diff)
downloadqemu-arm-fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0.tar.gz
Move target-* CPU file into a target/ folder
We've currently got 18 architectures in QEMU, and thus 18 target-xxx folders in the root folder of the QEMU source tree. More architectures (e.g. RISC-V, AVR) are likely to be included soon, too, so the main folder of the QEMU sources slowly gets quite overcrowded with the target-xxx folders. To disburden the main folder a little bit, let's move the target-xxx folders into a dedicated target/ folder, so that target-xxx/ simply becomes target/xxx/ instead. Acked-by: Laurent Vivier <laurent@vivier.eu> [m68k part] Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> [tricore part] Acked-by: Michael Walle <michael@walle.cc> [lm32 part] Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> [s390x part] Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> [s390x part] Acked-by: Eduardo Habkost <ehabkost@redhat.com> [i386 part] Acked-by: Artyom Tarasenko <atar4qemu@gmail.com> [sparc part] Acked-by: Richard Henderson <rth@twiddle.net> [alpha part] Acked-by: Max Filippov <jcmvbkbc@gmail.com> [xtensa part] Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ppc part] Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> [cris&microblaze part] Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn> [unicore32 part] Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/Makefile.objs7
-rw-r--r--target-i386/TODO31
-rw-r--r--target-i386/arch_dump.c453
-rw-r--r--target-i386/arch_memory_mapping.c281
-rw-r--r--target-i386/bpt_helper.c328
-rw-r--r--target-i386/cc_helper.c385
-rw-r--r--target-i386/cc_helper_template.h242
-rw-r--r--target-i386/cpu-qom.h77
-rw-r--r--target-i386/cpu.c3755
-rw-r--r--target-i386/cpu.h1656
-rw-r--r--target-i386/excp_helper.c137
-rw-r--r--target-i386/fpu_helper.c1625
-rw-r--r--target-i386/gdbstub.c234
-rw-r--r--target-i386/helper.c1446
-rw-r--r--target-i386/helper.h230
-rw-r--r--target-i386/hyperv.c140
-rw-r--r--target-i386/hyperv.h42
-rw-r--r--target-i386/int_helper.c483
-rw-r--r--target-i386/kvm-stub.c42
-rw-r--r--target-i386/kvm.c3536
-rw-r--r--target-i386/kvm_i386.h48
-rw-r--r--target-i386/machine.c1047
-rw-r--r--target-i386/mem_helper.c215
-rw-r--r--target-i386/misc_helper.c639
-rw-r--r--target-i386/monitor.c513
-rw-r--r--target-i386/mpx_helper.c168
-rw-r--r--target-i386/ops_sse.h2296
-rw-r--r--target-i386/ops_sse_header.h360
-rw-r--r--target-i386/seg_helper.c2568
-rw-r--r--target-i386/shift_helper_template.h108
-rw-r--r--target-i386/smm_helper.c342
-rw-r--r--target-i386/svm.h222
-rw-r--r--target-i386/svm_helper.c774
-rw-r--r--target-i386/trace-events7
-rw-r--r--target-i386/translate.c8502
35 files changed, 0 insertions, 32939 deletions
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
deleted file mode 100644
index b223d7932b..0000000000
--- a/target-i386/Makefile.objs
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-y += translate.o helper.o cpu.o bpt_helper.o
-obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
-obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o mpx_helper.o
-obj-y += gdbstub.o
-obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o
-obj-$(CONFIG_KVM) += kvm.o hyperv.o
-obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
diff --git a/target-i386/TODO b/target-i386/TODO
deleted file mode 100644
index a8d69cf87f..0000000000
--- a/target-i386/TODO
+++ /dev/null
@@ -1,31 +0,0 @@
-Correctness issues:
-
-- some eflags manipulation incorrectly reset the bit 0x2.
-- SVM: test, cpu save/restore, SMM save/restore.
-- x86_64: lcall/ljmp intel/amd differences ?
-- better code fetch (different exception handling + CS.limit support)
-- user/kernel PUSHL/POPL in helper.c
-- add missing cpuid tests
-- return UD exception if LOCK prefix incorrectly used
-- test ldt limit < 7 ?
-- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
-- full support of segment limit/rights
-- full x87 exception support
-- improve x87 bit exactness (use bochs code ?)
-- DRx register support
-- CR0.AC emulation
-- SSE alignment checks
-
-Optimizations/Features:
-
-- add SVM nested paging support
-- add VMX support
-- add AVX support
-- add SSE5 support
-- fxsave/fxrstor AMD extensions
-- improve monitor/mwait support
-- faster EFLAGS update: consider SZAP, C, O can be updated separately
- with a bit field in CC_OP and more state variables.
-- evaluate x87 stack pointer statically
-- find a way to avoid translating several time the same TB if CR0.TS
- is set or not.
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
deleted file mode 100644
index 5a2e4be5d0..0000000000
--- a/target-i386/arch_dump.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * i386 memory mapping
- *
- * Copyright Fujitsu, Corp. 2011, 2012
- *
- * Authors:
- * Wen Congyang <wency@cn.fujitsu.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/cpu-all.h"
-#include "sysemu/dump.h"
-#include "elf.h"
-#include "sysemu/memory_mapping.h"
-
-#ifdef TARGET_X86_64
-typedef struct {
- target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
- target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
- target_ulong rip, cs, eflags;
- target_ulong rsp, ss;
- target_ulong fs_base, gs_base;
- target_ulong ds, es, fs, gs;
-} x86_64_user_regs_struct;
-
-typedef struct {
- char pad1[32];
- uint32_t pid;
- char pad2[76];
- x86_64_user_regs_struct regs;
- char pad3[8];
-} x86_64_elf_prstatus;
-
-static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
- CPUX86State *env, int id,
- void *opaque)
-{
- x86_64_user_regs_struct regs;
- Elf64_Nhdr *note;
- char *buf;
- int descsz, note_size, name_size = 5;
- const char *name = "CORE";
- int ret;
-
- regs.r15 = env->regs[15];
- regs.r14 = env->regs[14];
- regs.r13 = env->regs[13];
- regs.r12 = env->regs[12];
- regs.r11 = env->regs[11];
- regs.r10 = env->regs[10];
- regs.r9 = env->regs[9];
- regs.r8 = env->regs[8];
- regs.rbp = env->regs[R_EBP];
- regs.rsp = env->regs[R_ESP];
- regs.rdi = env->regs[R_EDI];
- regs.rsi = env->regs[R_ESI];
- regs.rdx = env->regs[R_EDX];
- regs.rcx = env->regs[R_ECX];
- regs.rbx = env->regs[R_EBX];
- regs.rax = env->regs[R_EAX];
- regs.rip = env->eip;
- regs.eflags = env->eflags;
-
- regs.orig_rax = 0; /* FIXME */
- regs.cs = env->segs[R_CS].selector;
- regs.ss = env->segs[R_SS].selector;
- regs.fs_base = env->segs[R_FS].base;
- regs.gs_base = env->segs[R_GS].base;
- regs.ds = env->segs[R_DS].selector;
- regs.es = env->segs[R_ES].selector;
- regs.fs = env->segs[R_FS].selector;
- regs.gs = env->segs[R_GS].selector;
-
- descsz = sizeof(x86_64_elf_prstatus);
- note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
- (descsz + 3) / 4) * 4;
- note = g_malloc0(note_size);
- note->n_namesz = cpu_to_le32(name_size);
- note->n_descsz = cpu_to_le32(descsz);
- note->n_type = cpu_to_le32(NT_PRSTATUS);
- buf = (char *)note;
- buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
- memcpy(buf, name, name_size);
- buf += ((name_size + 3) / 4) * 4;
- memcpy(buf + 32, &id, 4); /* pr_pid */
- buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
- memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
-
- ret = f(note, note_size, opaque);
- g_free(note);
- if (ret < 0) {
- return -1;
- }
-
- return 0;
-}
-#endif
-
-typedef struct {
- uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
- unsigned short ds, __ds, es, __es;
- unsigned short fs, __fs, gs, __gs;
- uint32_t orig_eax, eip;
- unsigned short cs, __cs;
- uint32_t eflags, esp;
- unsigned short ss, __ss;
-} x86_user_regs_struct;
-
-typedef struct {
- char pad1[24];
- uint32_t pid;
- char pad2[44];
- x86_user_regs_struct regs;
- char pad3[4];
-} x86_elf_prstatus;
-
-static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
- int id)
-{
- memset(prstatus, 0, sizeof(x86_elf_prstatus));
- prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
- prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
- prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
- prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
- prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
- prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
- prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
- prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
- prstatus->regs.eip = env->eip & 0xffffffff;
- prstatus->regs.eflags = env->eflags & 0xffffffff;
-
- prstatus->regs.cs = env->segs[R_CS].selector;
- prstatus->regs.ss = env->segs[R_SS].selector;
- prstatus->regs.ds = env->segs[R_DS].selector;
- prstatus->regs.es = env->segs[R_ES].selector;
- prstatus->regs.fs = env->segs[R_FS].selector;
- prstatus->regs.gs = env->segs[R_GS].selector;
-
- prstatus->pid = id;
-}
-
-static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
- int id, void *opaque)
-{
- x86_elf_prstatus prstatus;
- Elf64_Nhdr *note;
- char *buf;
- int descsz, note_size, name_size = 5;
- const char *name = "CORE";
- int ret;
-
- x86_fill_elf_prstatus(&prstatus, env, id);
- descsz = sizeof(x86_elf_prstatus);
- note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
- (descsz + 3) / 4) * 4;
- note = g_malloc0(note_size);
- note->n_namesz = cpu_to_le32(name_size);
- note->n_descsz = cpu_to_le32(descsz);
- note->n_type = cpu_to_le32(NT_PRSTATUS);
- buf = (char *)note;
- buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
- memcpy(buf, name, name_size);
- buf += ((name_size + 3) / 4) * 4;
- memcpy(buf, &prstatus, sizeof(prstatus));
-
- ret = f(note, note_size, opaque);
- g_free(note);
- if (ret < 0) {
- return -1;
- }
-
- return 0;
-}
-
-int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque)
-{
- X86CPU *cpu = X86_CPU(cs);
- int ret;
-#ifdef TARGET_X86_64
- X86CPU *first_x86_cpu = X86_CPU(first_cpu);
- bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
-
- if (lma) {
- ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
- } else {
-#endif
- ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
-#ifdef TARGET_X86_64
- }
-#endif
-
- return ret;
-}
-
-int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque)
-{
- X86CPU *cpu = X86_CPU(cs);
- x86_elf_prstatus prstatus;
- Elf32_Nhdr *note;
- char *buf;
- int descsz, note_size, name_size = 5;
- const char *name = "CORE";
- int ret;
-
- x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
- descsz = sizeof(x86_elf_prstatus);
- note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
- (descsz + 3) / 4) * 4;
- note = g_malloc0(note_size);
- note->n_namesz = cpu_to_le32(name_size);
- note->n_descsz = cpu_to_le32(descsz);
- note->n_type = cpu_to_le32(NT_PRSTATUS);
- buf = (char *)note;
- buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
- memcpy(buf, name, name_size);
- buf += ((name_size + 3) / 4) * 4;
- memcpy(buf, &prstatus, sizeof(prstatus));
-
- ret = f(note, note_size, opaque);
- g_free(note);
- if (ret < 0) {
- return -1;
- }
-
- return 0;
-}
-
-/*
- * please count up QEMUCPUSTATE_VERSION if you have changed definition of
- * QEMUCPUState, and modify the tools using this information accordingly.
- */
-#define QEMUCPUSTATE_VERSION (1)
-
-struct QEMUCPUSegment {
- uint32_t selector;
- uint32_t limit;
- uint32_t flags;
- uint32_t pad;
- uint64_t base;
-};
-
-typedef struct QEMUCPUSegment QEMUCPUSegment;
-
-struct QEMUCPUState {
- uint32_t version;
- uint32_t size;
- uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
- uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
- uint64_t rip, rflags;
- QEMUCPUSegment cs, ds, es, fs, gs, ss;
- QEMUCPUSegment ldt, tr, gdt, idt;
- uint64_t cr[5];
-};
-
-typedef struct QEMUCPUState QEMUCPUState;
-
-static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
-{
- d->pad = 0;
- d->selector = s->selector;
- d->limit = s->limit;
- d->flags = s->flags;
- d->base = s->base;
-}
-
-static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
-{
- memset(s, 0, sizeof(QEMUCPUState));
-
- s->version = QEMUCPUSTATE_VERSION;
- s->size = sizeof(QEMUCPUState);
-
- s->rax = env->regs[R_EAX];
- s->rbx = env->regs[R_EBX];
- s->rcx = env->regs[R_ECX];
- s->rdx = env->regs[R_EDX];
- s->rsi = env->regs[R_ESI];
- s->rdi = env->regs[R_EDI];
- s->rsp = env->regs[R_ESP];
- s->rbp = env->regs[R_EBP];
-#ifdef TARGET_X86_64
- s->r8 = env->regs[8];
- s->r9 = env->regs[9];
- s->r10 = env->regs[10];
- s->r11 = env->regs[11];
- s->r12 = env->regs[12];
- s->r13 = env->regs[13];
- s->r14 = env->regs[14];
- s->r15 = env->regs[15];
-#endif
- s->rip = env->eip;
- s->rflags = env->eflags;
-
- copy_segment(&s->cs, &env->segs[R_CS]);
- copy_segment(&s->ds, &env->segs[R_DS]);
- copy_segment(&s->es, &env->segs[R_ES]);
- copy_segment(&s->fs, &env->segs[R_FS]);
- copy_segment(&s->gs, &env->segs[R_GS]);
- copy_segment(&s->ss, &env->segs[R_SS]);
- copy_segment(&s->ldt, &env->ldt);
- copy_segment(&s->tr, &env->tr);
- copy_segment(&s->gdt, &env->gdt);
- copy_segment(&s->idt, &env->idt);
-
- s->cr[0] = env->cr[0];
- s->cr[1] = env->cr[1];
- s->cr[2] = env->cr[2];
- s->cr[3] = env->cr[3];
- s->cr[4] = env->cr[4];
-}
-
-static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
- CPUX86State *env,
- void *opaque,
- int type)
-{
- QEMUCPUState state;
- Elf64_Nhdr *note64;
- Elf32_Nhdr *note32;
- void *note;
- char *buf;
- int descsz, note_size, name_size = 5, note_head_size;
- const char *name = "QEMU";
- int ret;
-
- qemu_get_cpustate(&state, env);
-
- descsz = sizeof(state);
- if (type == 0) {
- note_head_size = sizeof(Elf32_Nhdr);
- } else {
- note_head_size = sizeof(Elf64_Nhdr);
- }
- note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
- (descsz + 3) / 4) * 4;
- note = g_malloc0(note_size);
- if (type == 0) {
- note32 = note;
- note32->n_namesz = cpu_to_le32(name_size);
- note32->n_descsz = cpu_to_le32(descsz);
- note32->n_type = 0;
- } else {
- note64 = note;
- note64->n_namesz = cpu_to_le32(name_size);
- note64->n_descsz = cpu_to_le32(descsz);
- note64->n_type = 0;
- }
- buf = note;
- buf += ((note_head_size + 3) / 4) * 4;
- memcpy(buf, name, name_size);
- buf += ((name_size + 3) / 4) * 4;
- memcpy(buf, &state, sizeof(state));
-
- ret = f(note, note_size, opaque);
- g_free(note);
- if (ret < 0) {
- return -1;
- }
-
- return 0;
-}
-
-int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
- void *opaque)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
-}
-
-int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
- void *opaque)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
-}
-
-int cpu_get_dump_info(ArchDumpInfo *info,
- const GuestPhysBlockList *guest_phys_blocks)
-{
- bool lma = false;
- GuestPhysBlock *block;
-
-#ifdef TARGET_X86_64
- X86CPU *first_x86_cpu = X86_CPU(first_cpu);
-
- lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
-#endif
-
- if (lma) {
- info->d_machine = EM_X86_64;
- } else {
- info->d_machine = EM_386;
- }
- info->d_endian = ELFDATA2LSB;
-
- if (lma) {
- info->d_class = ELFCLASS64;
- } else {
- info->d_class = ELFCLASS32;
-
- QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
- if (block->target_end > UINT_MAX) {
- /* The memory size is greater than 4G */
- info->d_class = ELFCLASS64;
- break;
- }
- }
- }
-
- return 0;
-}
-
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
-{
- int name_size = 5; /* "CORE" or "QEMU" */
- size_t elf_note_size = 0;
- size_t qemu_note_size = 0;
- int elf_desc_size = 0;
- int qemu_desc_size = 0;
- int note_head_size;
-
- if (class == ELFCLASS32) {
- note_head_size = sizeof(Elf32_Nhdr);
- } else {
- note_head_size = sizeof(Elf64_Nhdr);
- }
-
- if (machine == EM_386) {
- elf_desc_size = sizeof(x86_elf_prstatus);
- }
-#ifdef TARGET_X86_64
- else {
- elf_desc_size = sizeof(x86_64_elf_prstatus);
- }
-#endif
- qemu_desc_size = sizeof(QEMUCPUState);
-
- elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
- (elf_desc_size + 3) / 4) * 4;
- qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
- (qemu_desc_size + 3) / 4) * 4;
-
- return (elf_note_size + qemu_note_size) * nr_cpus;
-}
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
deleted file mode 100644
index 88f341e1bb..0000000000
--- a/target-i386/arch_memory_mapping.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * i386 memory mapping
- *
- * Copyright Fujitsu, Corp. 2011, 2012
- *
- * Authors:
- * Wen Congyang <wency@cn.fujitsu.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/cpu-all.h"
-#include "sysemu/memory_mapping.h"
-
-/* PAE Paging or IA-32e Paging */
-static void walk_pte(MemoryMappingList *list, AddressSpace *as,
- hwaddr pte_start_addr,
- int32_t a20_mask, target_ulong start_line_addr)
-{
- hwaddr pte_addr, start_paddr;
- uint64_t pte;
- target_ulong start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pte_addr = (pte_start_addr + i * 8) & a20_mask;
- pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pte & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
-
- start_vaddr = start_line_addr | ((i & 0x1ff) << 12);
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 12);
- }
-}
-
-/* 32-bit Paging */
-static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pte_start_addr, int32_t a20_mask,
- target_ulong start_line_addr)
-{
- hwaddr pte_addr, start_paddr;
- uint32_t pte;
- target_ulong start_vaddr;
- int i;
-
- for (i = 0; i < 1024; i++) {
- pte_addr = (pte_start_addr + i * 4) & a20_mask;
- pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pte & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- start_paddr = pte & ~0xfff;
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
-
- start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 12);
- }
-}
-
-/* PAE Paging or IA-32e Paging */
-#define PLM4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */
-
-static void walk_pde(MemoryMappingList *list, AddressSpace *as,
- hwaddr pde_start_addr,
- int32_t a20_mask, target_ulong start_line_addr)
-{
- hwaddr pde_addr, pte_start_addr, start_paddr;
- uint64_t pde;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pde_addr = (pde_start_addr + i * 8) & a20_mask;
- pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pde & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = start_line_addr | ((i & 0x1ff) << 21);
- if (pde & PG_PSE_MASK) {
- /* 2 MB page */
- start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 21);
- continue;
- }
-
- pte_start_addr = (pde & PLM4_ADDR_MASK) & a20_mask;
- walk_pte(list, as, pte_start_addr, a20_mask, line_addr);
- }
-}
-
-/* 32-bit Paging */
-static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pde_start_addr, int32_t a20_mask,
- bool pse)
-{
- hwaddr pde_addr, pte_start_addr, start_paddr, high_paddr;
- uint32_t pde;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 1024; i++) {
- pde_addr = (pde_start_addr + i * 4) & a20_mask;
- pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pde & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = (((unsigned int)i & 0x3ff) << 22);
- if ((pde & PG_PSE_MASK) && pse) {
- /*
- * 4 MB page:
- * bits 39:32 are bits 20:13 of the PDE
- * bit3 31:22 are bits 31:22 of the PDE
- */
- high_paddr = ((hwaddr)(pde & 0x1fe000) << 19);
- start_paddr = (pde & ~0x3fffff) | high_paddr;
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 22);
- continue;
- }
-
- pte_start_addr = (pde & ~0xfff) & a20_mask;
- walk_pte2(list, as, pte_start_addr, a20_mask, line_addr);
- }
-}
-
-/* PAE Paging */
-static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pdpe_start_addr, int32_t a20_mask)
-{
- hwaddr pdpe_addr, pde_start_addr;
- uint64_t pdpe;
- target_ulong line_addr;
- int i;
-
- for (i = 0; i < 4; i++) {
- pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
- pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pdpe & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = (((unsigned int)i & 0x3) << 30);
- pde_start_addr = (pdpe & ~0xfff) & a20_mask;
- walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
- }
-}
-
-#ifdef TARGET_X86_64
-/* IA-32e Paging */
-static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
- hwaddr pdpe_start_addr, int32_t a20_mask,
- target_ulong start_line_addr)
-{
- hwaddr pdpe_addr, pde_start_addr, start_paddr;
- uint64_t pdpe;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
- pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pdpe & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
- if (pdpe & PG_PSE_MASK) {
- /* 1 GB page */
- start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 30);
- continue;
- }
-
- pde_start_addr = (pdpe & PLM4_ADDR_MASK) & a20_mask;
- walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
- }
-}
-
-/* IA-32e Paging */
-static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
- hwaddr pml4e_start_addr, int32_t a20_mask)
-{
- hwaddr pml4e_addr, pdpe_start_addr;
- uint64_t pml4e;
- target_ulong line_addr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
- pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
- NULL);
- if (!(pml4e & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
- pdpe_start_addr = (pml4e & PLM4_ADDR_MASK) & a20_mask;
- walk_pdpe(list, as, pdpe_start_addr, a20_mask, line_addr);
- }
-}
-#endif
-
-void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- if (!cpu_paging_enabled(cs)) {
- /* paging is disabled */
- return;
- }
-
- if (env->cr[4] & CR4_PAE_MASK) {
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- hwaddr pml4e_addr;
-
- pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & env->a20_mask;
- walk_pml4e(list, cs->as, pml4e_addr, env->a20_mask);
- } else
-#endif
- {
- hwaddr pdpe_addr;
-
- pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
- walk_pdpe2(list, cs->as, pdpe_addr, env->a20_mask);
- }
- } else {
- hwaddr pde_addr;
- bool pse;
-
- pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
- pse = !!(env->cr[4] & CR4_PSE_MASK);
- walk_pde2(list, cs->as, pde_addr, env->a20_mask, pse);
- }
-}
-
diff --git a/target-i386/bpt_helper.c b/target-i386/bpt_helper.c
deleted file mode 100644
index 6fd7fe04a0..0000000000
--- a/target-i386/bpt_helper.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * i386 breakpoint helpers
- *
- * 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 "cpu.h"
-#include "exec/exec-all.h"
-#include "exec/helper-proto.h"
-
-
-#ifndef CONFIG_USER_ONLY
-static inline bool hw_local_breakpoint_enabled(unsigned long dr7, int index)
-{
- return (dr7 >> (index * 2)) & 1;
-}
-
-static inline bool hw_global_breakpoint_enabled(unsigned long dr7, int index)
-{
- return (dr7 >> (index * 2)) & 2;
-
-}
-static inline bool hw_breakpoint_enabled(unsigned long dr7, int index)
-{
- return hw_global_breakpoint_enabled(dr7, index) ||
- hw_local_breakpoint_enabled(dr7, index);
-}
-
-static inline int hw_breakpoint_type(unsigned long dr7, int index)
-{
- return (dr7 >> (DR7_TYPE_SHIFT + (index * 4))) & 3;
-}
-
-static inline int hw_breakpoint_len(unsigned long dr7, int index)
-{
- int len = ((dr7 >> (DR7_LEN_SHIFT + (index * 4))) & 3);
- return (len == 2) ? 8 : len + 1;
-}
-
-static int hw_breakpoint_insert(CPUX86State *env, int index)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
- target_ulong dr7 = env->dr[7];
- target_ulong drN = env->dr[index];
- int err = 0;
-
- switch (hw_breakpoint_type(dr7, index)) {
- case DR7_TYPE_BP_INST:
- if (hw_breakpoint_enabled(dr7, index)) {
- err = cpu_breakpoint_insert(cs, drN, BP_CPU,
- &env->cpu_breakpoint[index]);
- }
- break;
-
- case DR7_TYPE_IO_RW:
- /* Notice when we should enable calls to bpt_io. */
- return hw_breakpoint_enabled(env->dr[7], index)
- ? HF_IOBPT_MASK : 0;
-
- case DR7_TYPE_DATA_WR:
- if (hw_breakpoint_enabled(dr7, index)) {
- err = cpu_watchpoint_insert(cs, drN,
- hw_breakpoint_len(dr7, index),
- BP_CPU | BP_MEM_WRITE,
- &env->cpu_watchpoint[index]);
- }
- break;
-
- case DR7_TYPE_DATA_RW:
- if (hw_breakpoint_enabled(dr7, index)) {
- err = cpu_watchpoint_insert(cs, drN,
- hw_breakpoint_len(dr7, index),
- BP_CPU | BP_MEM_ACCESS,
- &env->cpu_watchpoint[index]);
- }
- break;
- }
- if (err) {
- env->cpu_breakpoint[index] = NULL;
- }
- return 0;
-}
-
-static void hw_breakpoint_remove(CPUX86State *env, int index)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
-
- switch (hw_breakpoint_type(env->dr[7], index)) {
- case DR7_TYPE_BP_INST:
- if (env->cpu_breakpoint[index]) {
- cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
- env->cpu_breakpoint[index] = NULL;
- }
- break;
-
- case DR7_TYPE_DATA_WR:
- case DR7_TYPE_DATA_RW:
- if (env->cpu_breakpoint[index]) {
- cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
- env->cpu_breakpoint[index] = NULL;
- }
- break;
-
- case DR7_TYPE_IO_RW:
- /* HF_IOBPT_MASK cleared elsewhere. */
- break;
- }
-}
-
-void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7)
-{
- target_ulong old_dr7 = env->dr[7];
- int iobpt = 0;
- int i;
-
- new_dr7 |= DR7_FIXED_1;
-
- /* If nothing is changing except the global/local enable bits,
- then we can make the change more efficient. */
- if (((old_dr7 ^ new_dr7) & ~0xff) == 0) {
- /* Fold the global and local enable bits together into the
- global fields, then xor to show which registers have
- changed collective enable state. */
- int mod = ((old_dr7 | old_dr7 * 2) ^ (new_dr7 | new_dr7 * 2)) & 0xff;
-
- for (i = 0; i < DR7_MAX_BP; i++) {
- if ((mod & (2 << i * 2)) && !hw_breakpoint_enabled(new_dr7, i)) {
- hw_breakpoint_remove(env, i);
- }
- }
- env->dr[7] = new_dr7;
- for (i = 0; i < DR7_MAX_BP; i++) {
- if (mod & (2 << i * 2) && hw_breakpoint_enabled(new_dr7, i)) {
- iobpt |= hw_breakpoint_insert(env, i);
- } else if (hw_breakpoint_type(new_dr7, i) == DR7_TYPE_IO_RW
- && hw_breakpoint_enabled(new_dr7, i)) {
- iobpt |= HF_IOBPT_MASK;
- }
- }
- } else {
- for (i = 0; i < DR7_MAX_BP; i++) {
- hw_breakpoint_remove(env, i);
- }
- env->dr[7] = new_dr7;
- for (i = 0; i < DR7_MAX_BP; i++) {
- iobpt |= hw_breakpoint_insert(env, i);
- }
- }
-
- env->hflags = (env->hflags & ~HF_IOBPT_MASK) | iobpt;
-}
-
-static bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
-{
- target_ulong dr6;
- int reg;
- bool hit_enabled = false;
-
- dr6 = env->dr[6] & ~0xf;
- for (reg = 0; reg < DR7_MAX_BP; reg++) {
- bool bp_match = false;
- bool wp_match = false;
-
- switch (hw_breakpoint_type(env->dr[7], reg)) {
- case DR7_TYPE_BP_INST:
- if (env->dr[reg] == env->eip) {
- bp_match = true;
- }
- break;
- case DR7_TYPE_DATA_WR:
- case DR7_TYPE_DATA_RW:
- if (env->cpu_watchpoint[reg] &&
- env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
- wp_match = true;
- }
- break;
- case DR7_TYPE_IO_RW:
- break;
- }
- if (bp_match || wp_match) {
- dr6 |= 1 << reg;
- if (hw_breakpoint_enabled(env->dr[7], reg)) {
- hit_enabled = true;
- }
- }
- }
-
- if (hit_enabled || force_dr6_update) {
- env->dr[6] = dr6;
- }
-
- return hit_enabled;
-}
-
-void breakpoint_handler(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- CPUBreakpoint *bp;
-
- if (cs->watchpoint_hit) {
- if (cs->watchpoint_hit->flags & BP_CPU) {
- cs->watchpoint_hit = NULL;
- if (check_hw_breakpoints(env, false)) {
- raise_exception(env, EXCP01_DB);
- } else {
- cpu_loop_exit_noexc(cs);
- }
- }
- } else {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == env->eip) {
- if (bp->flags & BP_CPU) {
- check_hw_breakpoints(env, true);
- raise_exception(env, EXCP01_DB);
- }
- break;
- }
- }
- }
-}
-#endif
-
-void helper_single_step(CPUX86State *env)
-{
-#ifndef CONFIG_USER_ONLY
- check_hw_breakpoints(env, true);
- env->dr[6] |= DR6_BS;
-#endif
- raise_exception(env, EXCP01_DB);
-}
-
-void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
-{
-#ifndef CONFIG_USER_ONLY
- switch (reg) {
- case 0: case 1: case 2: case 3:
- if (hw_breakpoint_enabled(env->dr[7], reg)
- && hw_breakpoint_type(env->dr[7], reg) != DR7_TYPE_IO_RW) {
- hw_breakpoint_remove(env, reg);
- env->dr[reg] = t0;
- hw_breakpoint_insert(env, reg);
- } else {
- env->dr[reg] = t0;
- }
- return;
- case 4:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- }
- /* fallthru */
- case 6:
- env->dr[6] = t0 | DR6_FIXED_1;
- return;
- case 5:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- }
- /* fallthru */
- case 7:
- cpu_x86_update_dr7(env, t0);
- return;
- }
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
-#endif
-}
-
-target_ulong helper_get_dr(CPUX86State *env, int reg)
-{
- switch (reg) {
- case 0: case 1: case 2: case 3: case 6: case 7:
- return env->dr[reg];
- case 4:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- } else {
- return env->dr[6];
- }
- case 5:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- } else {
- return env->dr[7];
- }
- }
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
-}
-
-/* Check if Port I/O is trapped by a breakpoint. */
-void helper_bpt_io(CPUX86State *env, uint32_t port,
- uint32_t size, target_ulong next_eip)
-{
-#ifndef CONFIG_USER_ONLY
- target_ulong dr7 = env->dr[7];
- int i, hit = 0;
-
- for (i = 0; i < DR7_MAX_BP; ++i) {
- if (hw_breakpoint_type(dr7, i) == DR7_TYPE_IO_RW
- && hw_breakpoint_enabled(dr7, i)) {
- int bpt_len = hw_breakpoint_len(dr7, i);
- if (port + size - 1 >= env->dr[i]
- && port <= env->dr[i] + bpt_len - 1) {
- hit |= 1 << i;
- }
- }
- }
-
- if (hit) {
- env->dr[6] = (env->dr[6] & ~0xf) | hit;
- env->eip = next_eip;
- raise_exception(env, EXCP01_DB);
- }
-#endif
-}
diff --git a/target-i386/cc_helper.c b/target-i386/cc_helper.c
deleted file mode 100644
index 83af223c9f..0000000000
--- a/target-i386/cc_helper.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * x86 condition code helpers
- *
- * 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 "cpu.h"
-#include "exec/helper-proto.h"
-
-const uint8_t parity_table[256] = {
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
-};
-
-#define SHIFT 0
-#include "cc_helper_template.h"
-#undef SHIFT
-
-#define SHIFT 1
-#include "cc_helper_template.h"
-#undef SHIFT
-
-#define SHIFT 2
-#include "cc_helper_template.h"
-#undef SHIFT
-
-#ifdef TARGET_X86_64
-
-#define SHIFT 3
-#include "cc_helper_template.h"
-#undef SHIFT
-
-#endif
-
-static target_ulong compute_all_adcx(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- return (src1 & ~CC_C) | (dst * CC_C);
-}
-
-static target_ulong compute_all_adox(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- return (src1 & ~CC_O) | (src2 * CC_O);
-}
-
-static target_ulong compute_all_adcox(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- return (src1 & ~(CC_C | CC_O)) | (dst * CC_C) | (src2 * CC_O);
-}
-
-target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1,
- target_ulong src2, int op)
-{
- switch (op) {
- default: /* should never happen */
- return 0;
-
- case CC_OP_EFLAGS:
- return src1;
- case CC_OP_CLR:
- return CC_Z | CC_P;
-
- case CC_OP_MULB:
- return compute_all_mulb(dst, src1);
- case CC_OP_MULW:
- return compute_all_mulw(dst, src1);
- case CC_OP_MULL:
- return compute_all_mull(dst, src1);
-
- case CC_OP_ADDB:
- return compute_all_addb(dst, src1);
- case CC_OP_ADDW:
- return compute_all_addw(dst, src1);
- case CC_OP_ADDL:
- return compute_all_addl(dst, src1);
-
- case CC_OP_ADCB:
- return compute_all_adcb(dst, src1, src2);
- case CC_OP_ADCW:
- return compute_all_adcw(dst, src1, src2);
- case CC_OP_ADCL:
- return compute_all_adcl(dst, src1, src2);
-
- case CC_OP_SUBB:
- return compute_all_subb(dst, src1);
- case CC_OP_SUBW:
- return compute_all_subw(dst, src1);
- case CC_OP_SUBL:
- return compute_all_subl(dst, src1);
-
- case CC_OP_SBBB:
- return compute_all_sbbb(dst, src1, src2);
- case CC_OP_SBBW:
- return compute_all_sbbw(dst, src1, src2);
- case CC_OP_SBBL:
- return compute_all_sbbl(dst, src1, src2);
-
- case CC_OP_LOGICB:
- return compute_all_logicb(dst, src1);
- case CC_OP_LOGICW:
- return compute_all_logicw(dst, src1);
- case CC_OP_LOGICL:
- return compute_all_logicl(dst, src1);
-
- case CC_OP_INCB:
- return compute_all_incb(dst, src1);
- case CC_OP_INCW:
- return compute_all_incw(dst, src1);
- case CC_OP_INCL:
- return compute_all_incl(dst, src1);
-
- case CC_OP_DECB:
- return compute_all_decb(dst, src1);
- case CC_OP_DECW:
- return compute_all_decw(dst, src1);
- case CC_OP_DECL:
- return compute_all_decl(dst, src1);
-
- case CC_OP_SHLB:
- return compute_all_shlb(dst, src1);
- case CC_OP_SHLW:
- return compute_all_shlw(dst, src1);
- case CC_OP_SHLL:
- return compute_all_shll(dst, src1);
-
- case CC_OP_SARB:
- return compute_all_sarb(dst, src1);
- case CC_OP_SARW:
- return compute_all_sarw(dst, src1);
- case CC_OP_SARL:
- return compute_all_sarl(dst, src1);
-
- case CC_OP_BMILGB:
- return compute_all_bmilgb(dst, src1);
- case CC_OP_BMILGW:
- return compute_all_bmilgw(dst, src1);
- case CC_OP_BMILGL:
- return compute_all_bmilgl(dst, src1);
-
- case CC_OP_ADCX:
- return compute_all_adcx(dst, src1, src2);
- case CC_OP_ADOX:
- return compute_all_adox(dst, src1, src2);
- case CC_OP_ADCOX:
- return compute_all_adcox(dst, src1, src2);
-
-#ifdef TARGET_X86_64
- case CC_OP_MULQ:
- return compute_all_mulq(dst, src1);
- case CC_OP_ADDQ:
- return compute_all_addq(dst, src1);
- case CC_OP_ADCQ:
- return compute_all_adcq(dst, src1, src2);
- case CC_OP_SUBQ:
- return compute_all_subq(dst, src1);
- case CC_OP_SBBQ:
- return compute_all_sbbq(dst, src1, src2);
- case CC_OP_LOGICQ:
- return compute_all_logicq(dst, src1);
- case CC_OP_INCQ:
- return compute_all_incq(dst, src1);
- case CC_OP_DECQ:
- return compute_all_decq(dst, src1);
- case CC_OP_SHLQ:
- return compute_all_shlq(dst, src1);
- case CC_OP_SARQ:
- return compute_all_sarq(dst, src1);
- case CC_OP_BMILGQ:
- return compute_all_bmilgq(dst, src1);
-#endif
- }
-}
-
-uint32_t cpu_cc_compute_all(CPUX86State *env, int op)
-{
- return helper_cc_compute_all(CC_DST, CC_SRC, CC_SRC2, op);
-}
-
-target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1,
- target_ulong src2, int op)
-{
- switch (op) {
- default: /* should never happen */
- case CC_OP_LOGICB:
- case CC_OP_LOGICW:
- case CC_OP_LOGICL:
- case CC_OP_LOGICQ:
- case CC_OP_CLR:
- return 0;
-
- case CC_OP_EFLAGS:
- case CC_OP_SARB:
- case CC_OP_SARW:
- case CC_OP_SARL:
- case CC_OP_SARQ:
- case CC_OP_ADOX:
- return src1 & 1;
-
- case CC_OP_INCB:
- case CC_OP_INCW:
- case CC_OP_INCL:
- case CC_OP_INCQ:
- case CC_OP_DECB:
- case CC_OP_DECW:
- case CC_OP_DECL:
- case CC_OP_DECQ:
- return src1;
-
- case CC_OP_MULB:
- case CC_OP_MULW:
- case CC_OP_MULL:
- case CC_OP_MULQ:
- return src1 != 0;
-
- case CC_OP_ADCX:
- case CC_OP_ADCOX:
- return dst;
-
- case CC_OP_ADDB:
- return compute_c_addb(dst, src1);
- case CC_OP_ADDW:
- return compute_c_addw(dst, src1);
- case CC_OP_ADDL:
- return compute_c_addl(dst, src1);
-
- case CC_OP_ADCB:
- return compute_c_adcb(dst, src1, src2);
- case CC_OP_ADCW:
- return compute_c_adcw(dst, src1, src2);
- case CC_OP_ADCL:
- return compute_c_adcl(dst, src1, src2);
-
- case CC_OP_SUBB:
- return compute_c_subb(dst, src1);
- case CC_OP_SUBW:
- return compute_c_subw(dst, src1);
- case CC_OP_SUBL:
- return compute_c_subl(dst, src1);
-
- case CC_OP_SBBB:
- return compute_c_sbbb(dst, src1, src2);
- case CC_OP_SBBW:
- return compute_c_sbbw(dst, src1, src2);
- case CC_OP_SBBL:
- return compute_c_sbbl(dst, src1, src2);
-
- case CC_OP_SHLB:
- return compute_c_shlb(dst, src1);
- case CC_OP_SHLW:
- return compute_c_shlw(dst, src1);
- case CC_OP_SHLL:
- return compute_c_shll(dst, src1);
-
- case CC_OP_BMILGB:
- return compute_c_bmilgb(dst, src1);
- case CC_OP_BMILGW:
- return compute_c_bmilgw(dst, src1);
- case CC_OP_BMILGL:
- return compute_c_bmilgl(dst, src1);
-
-#ifdef TARGET_X86_64
- case CC_OP_ADDQ:
- return compute_c_addq(dst, src1);
- case CC_OP_ADCQ:
- return compute_c_adcq(dst, src1, src2);
- case CC_OP_SUBQ:
- return compute_c_subq(dst, src1);
- case CC_OP_SBBQ:
- return compute_c_sbbq(dst, src1, src2);
- case CC_OP_SHLQ:
- return compute_c_shlq(dst, src1);
- case CC_OP_BMILGQ:
- return compute_c_bmilgq(dst, src1);
-#endif
- }
-}
-
-void helper_write_eflags(CPUX86State *env, target_ulong t0,
- uint32_t update_mask)
-{
- cpu_load_eflags(env, t0, update_mask);
-}
-
-target_ulong helper_read_eflags(CPUX86State *env)
-{
- uint32_t eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- eflags |= (env->df & DF_MASK);
- eflags |= env->eflags & ~(VM_MASK | RF_MASK);
- return eflags;
-}
-
-void helper_clts(CPUX86State *env)
-{
- env->cr[0] &= ~CR0_TS_MASK;
- env->hflags &= ~HF_TS_MASK;
-}
-
-void helper_reset_rf(CPUX86State *env)
-{
- env->eflags &= ~RF_MASK;
-}
-
-void helper_cli(CPUX86State *env)
-{
- env->eflags &= ~IF_MASK;
-}
-
-void helper_sti(CPUX86State *env)
-{
- env->eflags |= IF_MASK;
-}
-
-void helper_clac(CPUX86State *env)
-{
- env->eflags &= ~AC_MASK;
-}
-
-void helper_stac(CPUX86State *env)
-{
- env->eflags |= AC_MASK;
-}
-
-#if 0
-/* vm86plus instructions */
-void helper_cli_vm(CPUX86State *env)
-{
- env->eflags &= ~VIF_MASK;
-}
-
-void helper_sti_vm(CPUX86State *env)
-{
- env->eflags |= VIF_MASK;
- if (env->eflags & VIP_MASK) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
-}
-#endif
diff --git a/target-i386/cc_helper_template.h b/target-i386/cc_helper_template.h
deleted file mode 100644
index 607311f195..0000000000
--- a/target-i386/cc_helper_template.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * x86 condition code helpers
- *
- * Copyright (c) 2008 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/>.
- */
-
-#define DATA_BITS (1 << (3 + SHIFT))
-
-#if DATA_BITS == 8
-#define SUFFIX b
-#define DATA_TYPE uint8_t
-#elif DATA_BITS == 16
-#define SUFFIX w
-#define DATA_TYPE uint16_t
-#elif DATA_BITS == 32
-#define SUFFIX l
-#define DATA_TYPE uint32_t
-#elif DATA_BITS == 64
-#define SUFFIX q
-#define DATA_TYPE uint64_t
-#else
-#error unhandled operand size
-#endif
-
-#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
-
-/* dynamic flags computation */
-
-static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src2 = dst - src1;
-
- cf = dst < src1;
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & CC_A;
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- return dst < src1;
-}
-
-static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
- DATA_TYPE src3)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src2 = dst - src1 - src3;
-
- cf = (src3 ? dst <= src1 : dst < src1);
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & 0x10;
- zf = (dst == 0) << 6;
- sf = lshift(dst, 8 - DATA_BITS) & 0x80;
- of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
- DATA_TYPE src3)
-{
- return src3 ? dst <= src1 : dst < src1;
-}
-
-static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src1 = dst + src2;
-
- cf = src1 < src2;
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & CC_A;
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
-{
- DATA_TYPE src1 = dst + src2;
-
- return src1 < src2;
-}
-
-static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
- DATA_TYPE src3)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src1 = dst + src2 + src3;
-
- cf = (src3 ? src1 <= src2 : src1 < src2);
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & 0x10;
- zf = (dst == 0) << 6;
- sf = lshift(dst, 8 - DATA_BITS) & 0x80;
- of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
- DATA_TYPE src3)
-{
- DATA_TYPE src1 = dst + src2 + src3;
-
- return (src3 ? src1 <= src2 : src1 < src2);
-}
-
-static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
-
- cf = 0;
- pf = parity_table[(uint8_t)dst];
- af = 0;
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = 0;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src2;
-
- cf = src1;
- src1 = dst - 1;
- src2 = 1;
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & CC_A;
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = (dst == SIGN_MASK) * CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
- DATA_TYPE src2;
-
- cf = src1;
- src1 = dst + 1;
- src2 = 1;
- pf = parity_table[(uint8_t)dst];
- af = (dst ^ src1 ^ src2) & CC_A;
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = (dst == SIGN_MASK - 1) * CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
-
- cf = (src1 >> (DATA_BITS - 1)) & CC_C;
- pf = parity_table[(uint8_t)dst];
- af = 0; /* undefined */
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- /* of is defined iff shift count == 1 */
- of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- return (src1 >> (DATA_BITS - 1)) & CC_C;
-}
-
-static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
-
- cf = src1 & 1;
- pf = parity_table[(uint8_t)dst];
- af = 0; /* undefined */
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- /* of is defined iff shift count == 1 */
- of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
- CF are modified and it is slower to do that. Note as well that we
- don't truncate SRC1 for computing carry to DATA_TYPE. */
-static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
-{
- int cf, pf, af, zf, sf, of;
-
- cf = (src1 != 0);
- pf = parity_table[(uint8_t)dst];
- af = 0; /* undefined */
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = cf * CC_O;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- int cf, pf, af, zf, sf, of;
-
- cf = (src1 == 0);
- pf = 0; /* undefined */
- af = 0; /* undefined */
- zf = (dst == 0) * CC_Z;
- sf = lshift(dst, 8 - DATA_BITS) & CC_S;
- of = 0;
- return cf | pf | af | zf | sf | of;
-}
-
-static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
-{
- return src1 == 0;
-}
-
-#undef DATA_BITS
-#undef SIGN_MASK
-#undef DATA_TYPE
-#undef DATA_MASK
-#undef SUFFIX
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
deleted file mode 100644
index 7c9a07ae65..0000000000
--- a/target-i386/cpu-qom.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * QEMU x86 CPU
- *
- * Copyright (c) 2012 SUSE LINUX Products GmbH
- *
- * 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.1 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/lgpl-2.1.html>
- */
-#ifndef QEMU_I386_CPU_QOM_H
-#define QEMU_I386_CPU_QOM_H
-
-#include "qom/cpu.h"
-#include "qemu/notify.h"
-
-#ifdef TARGET_X86_64
-#define TYPE_X86_CPU "x86_64-cpu"
-#else
-#define TYPE_X86_CPU "i386-cpu"
-#endif
-
-#define X86_CPU_CLASS(klass) \
- OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU)
-#define X86_CPU(obj) \
- OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU)
-#define X86_CPU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
-
-/**
- * X86CPUDefinition:
- *
- * CPU model definition data that was not converted to QOM per-subclass
- * property defaults yet.
- */
-typedef struct X86CPUDefinition X86CPUDefinition;
-
-/**
- * X86CPUClass:
- * @cpu_def: CPU model definition
- * @kvm_required: Whether CPU model requires KVM to be enabled.
- * @parent_realize: The parent class' realize handler.
- * @parent_reset: The parent class' reset handler.
- *
- * An x86 CPU model or family.
- */
-typedef struct X86CPUClass {
- /*< private >*/
- CPUClass parent_class;
- /*< public >*/
-
- /* Should be eventually replaced by subclass-specific property defaults. */
- X86CPUDefinition *cpu_def;
-
- bool kvm_required;
-
- /* Optional description of CPU model.
- * If unavailable, cpu_def->model_id is used */
- const char *model_description;
-
- DeviceRealize parent_realize;
- DeviceUnrealize parent_unrealize;
- void (*parent_reset)(CPUState *cpu);
-} X86CPUClass;
-
-typedef struct X86CPU X86CPU;
-
-#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
deleted file mode 100644
index de1f30eeda..0000000000
--- a/target-i386/cpu.c
+++ /dev/null
@@ -1,3755 +0,0 @@
-/*
- * 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/cutils.h"
-
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "sysemu/kvm.h"
-#include "sysemu/cpus.h"
-#include "kvm_i386.h"
-
-#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include "qemu/config-file.h"
-#include "qapi/qmp/qerror.h"
-
-#include "qapi-types.h"
-#include "qapi-visit.h"
-#include "qapi/visitor.h"
-#include "sysemu/arch_init.h"
-
-#if defined(CONFIG_KVM)
-#include <linux/kvm_para.h>
-#endif
-
-#include "sysemu/sysemu.h"
-#include "hw/qdev-properties.h"
-#include "hw/i386/topology.h"
-#ifndef CONFIG_USER_ONLY
-#include "exec/address-spaces.h"
-#include "hw/hw.h"
-#include "hw/xen/xen.h"
-#include "hw/i386/apic_internal.h"
-#endif
-
-
-/* Cache topology CPUID constants: */
-
-/* CPUID Leaf 2 Descriptors */
-
-#define CPUID_2_L1D_32KB_8WAY_64B 0x2c
-#define CPUID_2_L1I_32KB_8WAY_64B 0x30
-#define CPUID_2_L2_2MB_8WAY_64B 0x7d
-#define CPUID_2_L3_16MB_16WAY_64B 0x4d
-
-
-/* CPUID Leaf 4 constants: */
-
-/* EAX: */
-#define CPUID_4_TYPE_DCACHE 1
-#define CPUID_4_TYPE_ICACHE 2
-#define CPUID_4_TYPE_UNIFIED 3
-
-#define CPUID_4_LEVEL(l) ((l) << 5)
-
-#define CPUID_4_SELF_INIT_LEVEL (1 << 8)
-#define CPUID_4_FULLY_ASSOC (1 << 9)
-
-/* EDX: */
-#define CPUID_4_NO_INVD_SHARING (1 << 0)
-#define CPUID_4_INCLUSIVE (1 << 1)
-#define CPUID_4_COMPLEX_IDX (1 << 2)
-
-#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 */)
-
-
-/* Definitions of the hardcoded cache entries we expose: */
-
-/* L1 data cache: */
-#define L1D_LINE_SIZE 64
-#define L1D_ASSOCIATIVITY 8
-#define L1D_SETS 64
-#define L1D_PARTITIONS 1
-/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
-#define L1D_DESCRIPTOR CPUID_2_L1D_32KB_8WAY_64B
-/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
-#define L1D_LINES_PER_TAG 1
-#define L1D_SIZE_KB_AMD 64
-#define L1D_ASSOCIATIVITY_AMD 2
-
-/* L1 instruction cache: */
-#define L1I_LINE_SIZE 64
-#define L1I_ASSOCIATIVITY 8
-#define L1I_SETS 64
-#define L1I_PARTITIONS 1
-/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
-#define L1I_DESCRIPTOR CPUID_2_L1I_32KB_8WAY_64B
-/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
-#define L1I_LINES_PER_TAG 1
-#define L1I_SIZE_KB_AMD 64
-#define L1I_ASSOCIATIVITY_AMD 2
-
-/* Level 2 unified cache: */
-#define L2_LINE_SIZE 64
-#define L2_ASSOCIATIVITY 16
-#define L2_SETS 4096
-#define L2_PARTITIONS 1
-/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 4MiB */
-/*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */
-#define L2_DESCRIPTOR CPUID_2_L2_2MB_8WAY_64B
-/*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */
-#define L2_LINES_PER_TAG 1
-#define L2_SIZE_KB_AMD 512
-
-/* Level 3 unified cache: */
-#define L3_SIZE_KB 0 /* disabled */
-#define L3_ASSOCIATIVITY 0 /* disabled */
-#define L3_LINES_PER_TAG 0 /* disabled */
-#define L3_LINE_SIZE 0 /* disabled */
-#define L3_N_LINE_SIZE 64
-#define L3_N_ASSOCIATIVITY 16
-#define L3_N_SETS 16384
-#define L3_N_PARTITIONS 1
-#define L3_N_DESCRIPTOR CPUID_2_L3_16MB_16WAY_64B
-#define L3_N_LINES_PER_TAG 1
-#define L3_N_SIZE_KB_AMD 16384
-
-/* 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
-
-
-
-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)
- /* 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, CPUID_EXT_RDRAND */
-
-#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 0
-#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)
-#define TCG_7_0_EDX_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 struct FeatureWordInfo {
- /* 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[32];
- uint32_t cpuid_eax; /* Input EAX for CPUID */
- bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */
- uint32_t cpuid_ecx; /* Input ECX value for CPUID */
- int cpuid_reg; /* output register (R_* constant) */
- uint32_t tcg_features; /* Feature flags supported by TCG */
- uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */
- uint32_t migratable_flags; /* Feature flags known to be migratable */
-} FeatureWordInfo;
-
-static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
- [FEAT_1_EDX] = {
- .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, .cpuid_reg = R_EDX,
- .tcg_features = TCG_FEATURES,
- },
- [FEAT_1_ECX] = {
- .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", "osxsave",
- "avx", "f16c", "rdrand", "hypervisor",
- },
- .cpuid_eax = 1, .cpuid_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] = {
- .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, .cpuid_reg = R_EDX,
- .tcg_features = TCG_EXT2_FEATURES,
- },
- [FEAT_8000_0001_ECX] = {
- .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, .cpuid_reg = R_ECX,
- .tcg_features = TCG_EXT3_FEATURES,
- },
- [FEAT_C000_0001_EDX] = {
- .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, .cpuid_reg = R_EDX,
- .tcg_features = TCG_EXT4_FEATURES,
- },
- [FEAT_KVM] = {
- .feat_names = {
- "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock",
- "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt",
- NULL, NULL, NULL, NULL,
- NULL, NULL, 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, .cpuid_reg = R_EAX,
- .tcg_features = TCG_KVM_FEATURES,
- },
- [FEAT_HYPERV_EAX] = {
- .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, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- },
- .cpuid_eax = 0x40000003, .cpuid_reg = R_EAX,
- },
- [FEAT_HYPERV_EBX] = {
- .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, .cpuid_reg = R_EBX,
- },
- [FEAT_HYPERV_EDX] = {
- .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, .cpuid_reg = R_EDX,
- },
- [FEAT_SVM] = {
- .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, .cpuid_reg = R_EDX,
- .tcg_features = TCG_SVM_FEATURES,
- },
- [FEAT_7_0_EBX] = {
- .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", NULL, "avx512pf", "avx512er",
- "avx512cd", NULL, "avx512bw", "avx512vl",
- },
- .cpuid_eax = 7,
- .cpuid_needs_ecx = true, .cpuid_ecx = 0,
- .cpuid_reg = R_EBX,
- .tcg_features = TCG_7_0_EBX_FEATURES,
- },
- [FEAT_7_0_ECX] = {
- .feat_names = {
- NULL, "avx512vbmi", "umip", "pku",
- "ospke", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, "rdpid", NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- },
- .cpuid_eax = 7,
- .cpuid_needs_ecx = true, .cpuid_ecx = 0,
- .cpuid_reg = R_ECX,
- .tcg_features = TCG_7_0_ECX_FEATURES,
- },
- [FEAT_7_0_EDX] = {
- .feat_names = {
- NULL, NULL, "avx512-4vnniw", "avx512-4fmaps",
- 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 = 7,
- .cpuid_needs_ecx = true, .cpuid_ecx = 0,
- .cpuid_reg = R_EDX,
- .tcg_features = TCG_7_0_EDX_FEATURES,
- },
- [FEAT_8000_0007_EDX] = {
- .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,
- .cpuid_reg = R_EDX,
- .tcg_features = TCG_APM_FEATURES,
- .unmigratable_flags = CPUID_APM_INVTSC,
- },
- [FEAT_XSAVE] = {
- .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,
- .cpuid_needs_ecx = true, .cpuid_ecx = 1,
- .cpuid_reg = R_EAX,
- .tcg_features = TCG_XSAVE_FEATURES,
- },
- [FEAT_6_EAX] = {
- .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, .cpuid_reg = R_EAX,
- .tcg_features = TCG_6_EAX_FEATURES,
- },
- [FEAT_XSAVE_COMP_LO] = {
- .cpuid_eax = 0xD,
- .cpuid_needs_ecx = true, .cpuid_ecx = 0,
- .cpuid_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] = {
- .cpuid_eax = 0xD,
- .cpuid_needs_ecx = true, .cpuid_ecx = 0,
- .cpuid_reg = R_EDX,
- .tcg_features = ~0U,
- },
-};
-
-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 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 uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
-{
- FeatureWordInfo *wi = &feature_word_info[w];
- uint32_t r = 0;
- int i;
-
- for (i = 0; i < 32; i++) {
- uint32_t f = 1U << 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];
-}
-
-/* CPU class name definitions: */
-
-#define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU
-#define X86_CPU_TYPE_NAME(name) (name X86_CPU_TYPE_SUFFIX)
-
-/* 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)
-{
- ObjectClass *oc;
- char *typename;
-
- if (cpu_model == NULL) {
- return NULL;
- }
-
- typename = x86_cpu_type_name(cpu_model);
- oc = object_class_by_name(typename);
- g_free(typename);
- return oc;
-}
-
-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));
-}
-
-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;
- char model_id[48];
-};
-
-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,
- .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,
- .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,
- .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,
- .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,
- },
- {
- .name = "pentium",
- .level = 1,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 5,
- .model = 4,
- .stepping = 3,
- .features[FEAT_1_EDX] =
- PENTIUM_FEATURES,
- .xlevel = 0,
- },
- {
- .name = "pentium2",
- .level = 2,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 6,
- .model = 5,
- .stepping = 2,
- .features[FEAT_1_EDX] =
- PENTIUM2_FEATURES,
- .xlevel = 0,
- },
- {
- .name = "pentium3",
- .level = 3,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 6,
- .model = 7,
- .stepping = 3,
- .features[FEAT_1_EDX] =
- PENTIUM3_FEATURES,
- .xlevel = 0,
- },
- {
- .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,
- .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,
- .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,
- .xlevel = 0x80000008,
- .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
- },
- {
- .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,
- .xlevel = 0x80000008,
- .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
- },
- {
- .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,
- .xlevel = 0x80000008,
- .model_id = "Intel Xeon E312xx (Sandy Bridge)",
- },
- {
- .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,
- .xlevel = 0x80000008,
- .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)",
- },
- {
- .name = "Haswell-noTSX",
- .level = 0xd,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 6,
- .model = 60,
- .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_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_AVX2 | CPUID_7_0_EBX_SMEP |
- CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID,
- .features[FEAT_XSAVE] =
- CPUID_XSAVE_XSAVEOPT,
- .features[FEAT_6_EAX] =
- CPUID_6_EAX_ARAT,
- .xlevel = 0x80000008,
- .model_id = "Intel Core Processor (Haswell, no TSX)",
- }, {
- .name = "Haswell",
- .level = 0xd,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 6,
- .model = 60,
- .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_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,
- .xlevel = 0x80000008,
- .model_id = "Intel Core Processor (Haswell)",
- },
- {
- .name = "Broadwell-noTSX",
- .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 |
- 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 | CPUID_EXT3_3DNOWPREFETCH,
- .features[FEAT_7_0_EBX] =
- CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
- 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_RDSEED | CPUID_7_0_EBX_ADX |
- CPUID_7_0_EBX_SMAP,
- .features[FEAT_XSAVE] =
- CPUID_XSAVE_XSAVEOPT,
- .features[FEAT_6_EAX] =
- CPUID_6_EAX_ARAT,
- .xlevel = 0x80000008,
- .model_id = "Intel Core Processor (Broadwell, no TSX)",
- },
- {
- .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 |
- 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 | CPUID_EXT3_3DNOWPREFETCH,
- .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 | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
- CPUID_7_0_EBX_SMAP,
- .features[FEAT_XSAVE] =
- CPUID_XSAVE_XSAVEOPT,
- .features[FEAT_6_EAX] =
- CPUID_6_EAX_ARAT,
- .xlevel = 0x80000008,
- .model_id = "Intel Core Processor (Broadwell)",
- },
- {
- .name = "Skylake-Client",
- .level = 0xd,
- .vendor = CPUID_VENDOR_INTEL,
- .family = 6,
- .model = 94,
- .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_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 | CPUID_EXT3_3DNOWPREFETCH,
- .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 | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX,
- /* Missing: XSAVES (not supported by some Linux versions,
- * including v4.1 to v4.6).
- * KVM doesn't yet expose any XSAVES state save component,
- * and the only one defined in Skylake (processor tracing)
- * probably will block migration anyway.
- */
- .features[FEAT_XSAVE] =
- CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
- CPUID_XSAVE_XGETBV1,
- .features[FEAT_6_EAX] =
- CPUID_6_EAX_ARAT,
- .xlevel = 0x80000008,
- .model_id = "Intel Core Processor (Skylake)",
- },
- {
- .name = "Opteron_G1",
- .level = 5,
- .vendor = CPUID_VENDOR_AMD,
- .family = 15,
- .model = 6,
- .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_SSE3,
- .features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
- CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
- CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
- CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
- CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
- CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .xlevel = 0x80000008,
- .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)",
- },
- {
- .name = "Opteron_G2",
- .level = 5,
- .vendor = CPUID_VENDOR_AMD,
- .family = 15,
- .model = 6,
- .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_CX16 | CPUID_EXT_SSE3,
- /* Missing: CPUID_EXT2_RDTSCP */
- .features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_FXSR |
- CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
- CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
- CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
- CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
- CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
- CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
- .xlevel = 0x80000008,
- .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
- },
- {
- .name = "Opteron_G3",
- .level = 5,
- .vendor = CPUID_VENDOR_AMD,
- .family = 16,
- .model = 2,
- .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_CX16 | CPUID_EXT_MONITOR |
- CPUID_EXT_SSE3,
- /* Missing: CPUID_EXT2_RDTSCP */
- .features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_FXSR |
- CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
- CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
- CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
- CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
- CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
- CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
- CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
- .xlevel = 0x80000008,
- .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
- },
- {
- .name = "Opteron_G4",
- .level = 0xd,
- .vendor = CPUID_VENDOR_AMD,
- .family = 21,
- .model = 1,
- .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_SSE42 | CPUID_EXT_SSE41 |
- CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
- CPUID_EXT_SSE3,
- /* Missing: CPUID_EXT2_RDTSCP */
- .features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM |
- CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
- CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
- CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
- CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
- CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
- CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
- CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
- CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
- CPUID_EXT3_LAHF_LM,
- /* no xsaveopt! */
- .xlevel = 0x8000001A,
- .model_id = "AMD Opteron 62xx class CPU",
- },
- {
- .name = "Opteron_G5",
- .level = 0xd,
- .vendor = CPUID_VENDOR_AMD,
- .family = 21,
- .model = 2,
- .stepping = 0,
- .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_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
- CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
- CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
- CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
- /* Missing: CPUID_EXT2_RDTSCP */
- .features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM |
- CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
- CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
- CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
- CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
- CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
- CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
- CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
- CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
- CPUID_EXT3_LAHF_LM,
- /* no xsaveopt! */
- .xlevel = 0x8000001A,
- .model_id = "AMD Opteron 63xx class CPU",
- },
-};
-
-typedef struct PropValue {
- const char *prop, *value;
-} PropValue;
-
-/* KVM-specific features that are automatically added/removed
- * from all CPU models when KVM is enabled.
- */
-static PropValue kvm_default_props[] = {
- { "kvmclock", "on" },
- { "kvm-nopiodelay", "on" },
- { "kvm-asyncpf", "on" },
- { "kvm-steal-time", "on" },
- { "kvm-pv-eoi", "on" },
- { "kvmclock-stable-bit", "on" },
- { "x2apic", "on" },
- { "acpi", "off" },
- { "monitor", "off" },
- { "svm", "off" },
- { NULL, NULL },
-};
-
-/* TCG-specific defaults that override all CPU models when using TCG
- */
-static PropValue tcg_default_props[] = {
- { "vme", "off" },
- { NULL, NULL },
-};
-
-
-void x86_cpu_change_kvm_default(const char *prop, const char *value)
-{
- PropValue *pv;
- for (pv = kvm_default_props; pv->prop; pv++) {
- if (!strcmp(pv->prop, prop)) {
- pv->value = value;
- break;
- }
- }
-
- /* It is valid to call this function only for properties that
- * are already present in the kvm_default_props table.
- */
- assert(pv->prop);
-}
-
-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
- bool migratable_only);
-
-#ifdef CONFIG_KVM
-
-static bool lmce_supported(void)
-{
- uint64_t mce_cap;
-
- if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
- return false;
- }
-
- return !!(mce_cap & MCG_LMCE_P);
-}
-
-static int cpu_x86_fill_model_id(char *str)
-{
- uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
- int i;
-
- for (i = 0; i < 3; i++) {
- host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
- memcpy(str + i * 16 + 0, &eax, 4);
- memcpy(str + i * 16 + 4, &ebx, 4);
- memcpy(str + i * 16 + 8, &ecx, 4);
- memcpy(str + i * 16 + 12, &edx, 4);
- }
- return 0;
-}
-
-static X86CPUDefinition host_cpudef;
-
-static Property host_x86_cpu_properties[] = {
- DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
- DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough, false),
- DEFINE_PROP_END_OF_LIST()
-};
-
-/* class_init for the "host" CPU model
- *
- * This function may be called before KVM is initialized.
- */
-static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- X86CPUClass *xcc = X86_CPU_CLASS(oc);
- uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-
- xcc->kvm_required = true;
-
- host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
- x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
-
- host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
- host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
- host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
- host_cpudef.stepping = eax & 0x0F;
-
- cpu_x86_fill_model_id(host_cpudef.model_id);
-
- xcc->cpu_def = &host_cpudef;
- xcc->model_description =
- "KVM processor with all supported host features "
- "(only available in KVM mode)";
-
- /* level, xlevel, xlevel2, and the feature words are initialized on
- * instance_init, because they require KVM to be initialized.
- */
-
- dc->props = host_x86_cpu_properties;
- /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
- dc->cannot_destroy_with_object_finalize_yet = true;
-}
-
-static void host_x86_cpu_initfn(Object *obj)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- KVMState *s = kvm_state;
-
- /* We can't fill the features array here because we don't know yet if
- * "migratable" is true or false.
- */
- cpu->host_features = true;
-
- /* If KVM is disabled, x86_cpu_realizefn() will report an error later */
- if (kvm_enabled()) {
- env->cpuid_min_level =
- kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
- env->cpuid_min_xlevel =
- kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
- env->cpuid_min_xlevel2 =
- kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
-
- if (lmce_supported()) {
- object_property_set_bool(OBJECT(cpu), true, "lmce", &error_abort);
- }
- }
-
- object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
-}
-
-static const TypeInfo host_x86_cpu_type_info = {
- .name = X86_CPU_TYPE_NAME("host"),
- .parent = TYPE_X86_CPU,
- .instance_init = host_x86_cpu_initfn,
- .class_init = host_x86_cpu_class_init,
-};
-
-#endif
-
-static void report_unavailable_features(FeatureWord w, uint32_t mask)
-{
- FeatureWordInfo *f = &feature_word_info[w];
- int i;
-
- for (i = 0; i < 32; ++i) {
- if ((1UL << i) & mask) {
- const char *reg = get_register_name_32(f->cpuid_reg);
- assert(reg);
- fprintf(stderr, "warning: %s doesn't support requested feature: "
- "CPUID.%02XH:%s%s%s [bit %d]\n",
- kvm_enabled() ? "host" : "TCG",
- f->cpuid_eax, reg,
- f->feat_names[i] ? "." : "",
- f->feat_names[i] ? f->feat_names[i] : "", i);
- }
- }
-}
-
-static void x86_cpuid_version_get_family(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- int64_t value;
-
- value = (env->cpuid_version >> 8) & 0xf;
- if (value == 0xf) {
- value += (env->cpuid_version >> 20) & 0xff;
- }
- visit_type_int(v, name, &value, errp);
-}
-
-static void x86_cpuid_version_set_family(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- const int64_t min = 0;
- const int64_t max = 0xff + 0xf;
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value < min || value > max) {
- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
-
- env->cpuid_version &= ~0xff00f00;
- if (value > 0x0f) {
- env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
- } else {
- env->cpuid_version |= value << 8;
- }
-}
-
-static void x86_cpuid_version_get_model(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- int64_t value;
-
- value = (env->cpuid_version >> 4) & 0xf;
- value |= ((env->cpuid_version >> 16) & 0xf) << 4;
- visit_type_int(v, name, &value, errp);
-}
-
-static void x86_cpuid_version_set_model(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- const int64_t min = 0;
- const int64_t max = 0xff;
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value < min || value > max) {
- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
-
- env->cpuid_version &= ~0xf00f0;
- env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
-}
-
-static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- int64_t value;
-
- value = env->cpuid_version & 0xf;
- visit_type_int(v, name, &value, errp);
-}
-
-static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- const int64_t min = 0;
- const int64_t max = 0xf;
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value < min || value > max) {
- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
-
- env->cpuid_version &= ~0xf;
- env->cpuid_version |= value & 0xf;
-}
-
-static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- char *value;
-
- value = g_malloc(CPUID_VENDOR_SZ + 1);
- x86_cpu_vendor_words2str(value, env->cpuid_vendor1, env->cpuid_vendor2,
- env->cpuid_vendor3);
- return value;
-}
-
-static void x86_cpuid_set_vendor(Object *obj, const char *value,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- int i;
-
- if (strlen(value) != CPUID_VENDOR_SZ) {
- error_setg(errp, QERR_PROPERTY_VALUE_BAD, "", "vendor", value);
- return;
- }
-
- env->cpuid_vendor1 = 0;
- env->cpuid_vendor2 = 0;
- env->cpuid_vendor3 = 0;
- for (i = 0; i < 4; i++) {
- env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
- env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
- env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
- }
-}
-
-static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- char *value;
- int i;
-
- value = g_malloc(48 + 1);
- for (i = 0; i < 48; i++) {
- value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
- }
- value[48] = '\0';
- return value;
-}
-
-static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
- Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- CPUX86State *env = &cpu->env;
- int c, len, i;
-
- if (model_id == NULL) {
- model_id = "";
- }
- len = strlen(model_id);
- memset(env->cpuid_model, 0, 48);
- for (i = 0; i < 48; i++) {
- if (i >= len) {
- c = '\0';
- } else {
- c = (uint8_t)model_id[i];
- }
- env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
- }
-}
-
-static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- int64_t value;
-
- value = cpu->env.tsc_khz * 1000;
- visit_type_int(v, name, &value, errp);
-}
-
-static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- const int64_t min = 0;
- const int64_t max = INT64_MAX;
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value < min || value > max) {
- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
-
- cpu->env.tsc_khz = cpu->env.user_tsc_khz = value / 1000;
-}
-
-/* Generic getter for "feature-words" and "filtered-features" properties */
-static void x86_cpu_get_feature_words(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- uint32_t *array = (uint32_t *)opaque;
- FeatureWord w;
- X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { };
- X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { };
- X86CPUFeatureWordInfoList *list = NULL;
-
- for (w = 0; w < FEATURE_WORDS; w++) {
- FeatureWordInfo *wi = &feature_word_info[w];
- X86CPUFeatureWordInfo *qwi = &word_infos[w];
- qwi->cpuid_input_eax = wi->cpuid_eax;
- qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx;
- qwi->cpuid_input_ecx = wi->cpuid_ecx;
- qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum;
- qwi->features = array[w];
-
- /* List will be in reverse order, but order shouldn't matter */
- list_entries[w].next = list;
- list_entries[w].value = &word_infos[w];
- list = &list_entries[w];
- }
-
- visit_type_X86CPUFeatureWordInfoList(v, "feature-words", &list, errp);
-}
-
-static void x86_get_hv_spinlocks(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- X86CPU *cpu = X86_CPU(obj);
- int64_t value = cpu->hyperv_spinlock_attempts;
-
- visit_type_int(v, name, &value, errp);
-}
-
-static void x86_set_hv_spinlocks(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- const int64_t min = 0xFFF;
- const int64_t max = UINT_MAX;
- X86CPU *cpu = X86_CPU(obj);
- Error *err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- if (value < min || value > max) {
- error_setg(errp, "Property %s.%s doesn't take value %" PRId64
- " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
- object_get_typename(obj), name ? name : "null",
- value, min, max);
- return;
- }
- cpu->hyperv_spinlock_attempts = value;
-}
-
-static PropertyInfo qdev_prop_spinlocks = {
- .name = "int",
- .get = x86_get_hv_spinlocks,
- .set = x86_set_hv_spinlocks,
-};
-
-/* Convert all '_' in a feature string option name to '-', to make feature
- * name conform to QOM property naming rule, which uses '-' instead of '_'.
- */
-static inline void feat2prop(char *s)
-{
- while ((s = strchr(s, '_'))) {
- *s = '-';
- }
-}
-
-/* Return the feature property name for a feature flag bit */
-static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
-{
- /* XSAVE components are automatically enabled by other features,
- * so return the original feature name instead
- */
- if (w == FEAT_XSAVE_COMP_LO || w == FEAT_XSAVE_COMP_HI) {
- int comp = (w == FEAT_XSAVE_COMP_HI) ? bitnr + 32 : bitnr;
-
- if (comp < ARRAY_SIZE(x86_ext_save_areas) &&
- x86_ext_save_areas[comp].bits) {
- w = x86_ext_save_areas[comp].feature;
- bitnr = ctz32(x86_ext_save_areas[comp].bits);
- }
- }
-
- assert(bitnr < 32);
- assert(w < FEATURE_WORDS);
- return feature_word_info[w].feat_names[bitnr];
-}
-
-/* Compatibily hack to maintain legacy +-feat semantic,
- * where +-feat overwrites any feature set by
- * feat=on|feat even if the later is parsed after +-feat
- * (i.e. "-x2apic,x2apic=on" will result in x2apic disabled)
- */
-static GList *plus_features, *minus_features;
-
-static gint compare_string(gconstpointer a, gconstpointer b)
-{
- return g_strcmp0(a, b);
-}
-
-/* Parse "+feature,-feature,feature=foo" CPU feature string
- */
-static void x86_cpu_parse_featurestr(const char *typename, char *features,
- Error **errp)
-{
- char *featurestr; /* Single 'key=value" string being parsed */
- static bool cpu_globals_initialized;
- bool ambiguous = false;
-
- if (cpu_globals_initialized) {
- return;
- }
- cpu_globals_initialized = true;
-
- if (!features) {
- return;
- }
-
- for (featurestr = strtok(features, ",");
- featurestr;
- featurestr = strtok(NULL, ",")) {
- const char *name;
- const char *val = NULL;
- char *eq = NULL;
- char num[32];
- GlobalProperty *prop;
-
- /* Compatibility syntax: */
- if (featurestr[0] == '+') {
- plus_features = g_list_append(plus_features,
- g_strdup(featurestr + 1));
- continue;
- } else if (featurestr[0] == '-') {
- minus_features = g_list_append(minus_features,
- g_strdup(featurestr + 1));
- continue;
- }
-
- eq = strchr(featurestr, '=');
- if (eq) {
- *eq++ = 0;
- val = eq;
- } else {
- val = "on";
- }
-
- feat2prop(featurestr);
- name = featurestr;
-
- if (g_list_find_custom(plus_features, name, compare_string)) {
- error_report("warning: Ambiguous CPU model string. "
- "Don't mix both \"+%s\" and \"%s=%s\"",
- name, name, val);
- ambiguous = true;
- }
- if (g_list_find_custom(minus_features, name, compare_string)) {
- error_report("warning: Ambiguous CPU model string. "
- "Don't mix both \"-%s\" and \"%s=%s\"",
- name, name, val);
- ambiguous = true;
- }
-
- /* Special case: */
- if (!strcmp(name, "tsc-freq")) {
- int64_t tsc_freq;
- char *err;
-
- tsc_freq = qemu_strtosz_suffix_unit(val, &err,
- QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
- if (tsc_freq < 0 || *err) {
- error_setg(errp, "bad numerical value %s", val);
- return;
- }
- snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
- val = num;
- name = "tsc-frequency";
- }
-
- prop = g_new0(typeof(*prop), 1);
- prop->driver = typename;
- prop->property = g_strdup(name);
- prop->value = g_strdup(val);
- prop->errp = &error_fatal;
- qdev_prop_register_global(prop);
- }
-
- if (ambiguous) {
- error_report("warning: Compatibility of ambiguous CPU model "
- "strings won't be kept on future QEMU versions");
- }
-}
-
-static void x86_cpu_load_features(X86CPU *cpu, Error **errp);
-static int x86_cpu_filter_features(X86CPU *cpu);
-
-/* Check for missing features that may prevent the CPU class from
- * running using the current machine and accelerator.
- */
-static void x86_cpu_class_check_missing_features(X86CPUClass *xcc,
- strList **missing_feats)
-{
- X86CPU *xc;
- FeatureWord w;
- Error *err = NULL;
- strList **next = missing_feats;
-
- if (xcc->kvm_required && !kvm_enabled()) {
- strList *new = g_new0(strList, 1);
- new->value = g_strdup("kvm");;
- *missing_feats = new;
- return;
- }
-
- xc = X86_CPU(object_new(object_class_get_name(OBJECT_CLASS(xcc))));
-
- x86_cpu_load_features(xc, &err);
- if (err) {
- /* Errors at x86_cpu_load_features should never happen,
- * but in case it does, just report the model as not
- * runnable at all using the "type" property.
- */
- strList *new = g_new0(strList, 1);
- new->value = g_strdup("type");
- *next = new;
- next = &new->next;
- }
-
- x86_cpu_filter_features(xc);
-
- for (w = 0; w < FEATURE_WORDS; w++) {
- uint32_t filtered = xc->filtered_features[w];
- int i;
- for (i = 0; i < 32; i++) {
- if (filtered & (1UL << i)) {
- strList *new = g_new0(strList, 1);
- new->value = g_strdup(x86_cpu_feature_name(w, i));
- *next = new;
- next = &new->next;
- }
- }
- }
-
- object_unref(OBJECT(xc));
-}
-
-/* Print all cpuid feature names in featureset
- */
-static void listflags(FILE *f, fprintf_function print, const char **featureset)
-{
- int bit;
- bool first = true;
-
- for (bit = 0; bit < 32; bit++) {
- if (featureset[bit]) {
- print(f, "%s%s", first ? "" : " ", featureset[bit]);
- first = false;
- }
- }
-}
-
-/* Sort alphabetically by type name, listing kvm_required models last. */
-static gint x86_cpu_list_compare(gconstpointer a, gconstpointer b)
-{
- ObjectClass *class_a = (ObjectClass *)a;
- ObjectClass *class_b = (ObjectClass *)b;
- X86CPUClass *cc_a = X86_CPU_CLASS(class_a);
- X86CPUClass *cc_b = X86_CPU_CLASS(class_b);
- const char *name_a, *name_b;
-
- if (cc_a->kvm_required != cc_b->kvm_required) {
- /* kvm_required items go last */
- return cc_a->kvm_required ? 1 : -1;
- } else {
- name_a = object_class_get_name(class_a);
- name_b = object_class_get_name(class_b);
- return strcmp(name_a, name_b);
- }
-}
-
-static GSList *get_sorted_cpu_model_list(void)
-{
- GSList *list = object_class_get_list(TYPE_X86_CPU, false);
- list = g_slist_sort(list, x86_cpu_list_compare);
- return list;
-}
-
-static void x86_cpu_list_entry(gpointer data, gpointer user_data)
-{
- ObjectClass *oc = data;
- X86CPUClass *cc = X86_CPU_CLASS(oc);
- CPUListState *s = user_data;
- char *name = x86_cpu_class_get_model_name(cc);
- const char *desc = cc->model_description;
- if (!desc) {
- desc = cc->cpu_def->model_id;
- }
-
- (*s->cpu_fprintf)(s->file, "x86 %16s %-48s\n",
- name, desc);
- g_free(name);
-}
-
-/* list available CPU models and flags */
-void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
- int i;
- CPUListState s = {
- .file = f,
- .cpu_fprintf = cpu_fprintf,
- };
- GSList *list;
-
- (*cpu_fprintf)(f, "Available CPUs:\n");
- list = get_sorted_cpu_model_list();
- g_slist_foreach(list, x86_cpu_list_entry, &s);
- g_slist_free(list);
-
- (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n");
- for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
- FeatureWordInfo *fw = &feature_word_info[i];
-
- (*cpu_fprintf)(f, " ");
- listflags(f, cpu_fprintf, fw->feat_names);
- (*cpu_fprintf)(f, "\n");
- }
-}
-
-static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
-{
- ObjectClass *oc = data;
- X86CPUClass *cc = X86_CPU_CLASS(oc);
- CpuDefinitionInfoList **cpu_list = user_data;
- CpuDefinitionInfoList *entry;
- CpuDefinitionInfo *info;
-
- info = g_malloc0(sizeof(*info));
- info->name = x86_cpu_class_get_model_name(cc);
- x86_cpu_class_check_missing_features(cc, &info->unavailable_features);
- info->has_unavailable_features = true;
-
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = *cpu_list;
- *cpu_list = entry;
-}
-
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
-{
- CpuDefinitionInfoList *cpu_list = NULL;
- GSList *list = get_sorted_cpu_model_list();
- g_slist_foreach(list, x86_cpu_definition_entry, &cpu_list);
- g_slist_free(list);
- return cpu_list;
-}
-
-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
- bool migratable_only)
-{
- FeatureWordInfo *wi = &feature_word_info[w];
- uint32_t r;
-
- if (kvm_enabled()) {
- r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax,
- wi->cpuid_ecx,
- wi->cpuid_reg);
- } else if (tcg_enabled()) {
- r = wi->tcg_features;
- } else {
- return ~0;
- }
- if (migratable_only) {
- r &= x86_cpu_get_migratable_flags(w);
- }
- return r;
-}
-
-/*
- * Filters CPU feature words based on host availability of each feature.
- *
- * Returns: 0 if all flags are supported by the host, non-zero otherwise.
- */
-static int x86_cpu_filter_features(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- FeatureWord w;
- int rv = 0;
-
- for (w = 0; w < FEATURE_WORDS; w++) {
- uint32_t host_feat =
- x86_cpu_get_supported_feature_word(w, false);
- uint32_t requested_features = env->features[w];
- env->features[w] &= host_feat;
- cpu->filtered_features[w] = requested_features & ~env->features[w];
- if (cpu->filtered_features[w]) {
- rv = 1;
- }
- }
-
- return rv;
-}
-
-static void x86_cpu_report_filtered_features(X86CPU *cpu)
-{
- FeatureWord w;
-
- for (w = 0; w < FEATURE_WORDS; w++) {
- report_unavailable_features(w, cpu->filtered_features[w]);
- }
-}
-
-static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
-{
- PropValue *pv;
- for (pv = props; pv->prop; pv++) {
- if (!pv->value) {
- continue;
- }
- object_property_parse(OBJECT(cpu), pv->value, pv->prop,
- &error_abort);
- }
-}
-
-/* Load data from X86CPUDefinition
- */
-static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
-{
- CPUX86State *env = &cpu->env;
- const char *vendor;
- char host_vendor[CPUID_VENDOR_SZ + 1];
- FeatureWord w;
-
- /* CPU models only set _minimum_ values for level/xlevel: */
- object_property_set_int(OBJECT(cpu), def->level, "min-level", errp);
- object_property_set_int(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
-
- object_property_set_int(OBJECT(cpu), def->family, "family", errp);
- object_property_set_int(OBJECT(cpu), def->model, "model", errp);
- object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
- object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
- for (w = 0; w < FEATURE_WORDS; w++) {
- env->features[w] = def->features[w];
- }
-
- /* Special cases not set in the X86CPUDefinition structs: */
- if (kvm_enabled()) {
- if (!kvm_irqchip_in_kernel()) {
- x86_cpu_change_kvm_default("x2apic", "off");
- }
-
- x86_cpu_apply_props(cpu, kvm_default_props);
- } else if (tcg_enabled()) {
- x86_cpu_apply_props(cpu, tcg_default_props);
- }
-
- env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
-
- /* sysenter isn't supported in compatibility mode on AMD,
- * syscall isn't supported in compatibility mode on Intel.
- * Normally we advertise the actual CPU vendor, but you can
- * override this using the 'vendor' property if you want to use
- * KVM's sysenter/syscall emulation in compatibility mode and
- * when doing cross vendor migration
- */
- vendor = def->vendor;
- if (kvm_enabled()) {
- uint32_t ebx = 0, ecx = 0, edx = 0;
- host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
- x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx);
- vendor = host_vendor;
- }
-
- object_property_set_str(OBJECT(cpu), vendor, "vendor", errp);
-
-}
-
-X86CPU *cpu_x86_init(const char *cpu_model)
-{
- return X86_CPU(cpu_generic_init(TYPE_X86_CPU, cpu_model));
-}
-
-static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
-{
- X86CPUDefinition *cpudef = data;
- X86CPUClass *xcc = X86_CPU_CLASS(oc);
-
- xcc->cpu_def = cpudef;
-}
-
-static void x86_register_cpudef_type(X86CPUDefinition *def)
-{
- char *typename = x86_cpu_type_name(def->name);
- TypeInfo ti = {
- .name = typename,
- .parent = TYPE_X86_CPU,
- .class_init = x86_cpu_cpudef_class_init,
- .class_data = def,
- };
-
- type_register(&ti);
- g_free(typename);
-}
-
-#if !defined(CONFIG_USER_ONLY)
-
-void cpu_clear_apic_feature(CPUX86State *env)
-{
- env->features[FEAT_1_EDX] &= ~CPUID_APIC;
-}
-
-#endif /* !CONFIG_USER_ONLY */
-
-void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
- CPUState *cs = CPU(cpu);
- uint32_t pkg_offset;
-
- /* test if maximum index reached */
- if (index & 0x80000000) {
- if (index > env->cpuid_xlevel) {
- if (env->cpuid_xlevel2 > 0) {
- /* Handle the Centaur's CPUID instruction. */
- if (index > env->cpuid_xlevel2) {
- index = env->cpuid_xlevel2;
- } else if (index < 0xC0000000) {
- index = env->cpuid_xlevel;
- }
- } else {
- /* Intel documentation states that invalid EAX input will
- * return the same information as EAX=cpuid_level
- * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID)
- */
- index = env->cpuid_level;
- }
- }
- } else {
- if (index > env->cpuid_level)
- index = env->cpuid_level;
- }
-
- switch(index) {
- case 0:
- *eax = env->cpuid_level;
- *ebx = env->cpuid_vendor1;
- *edx = env->cpuid_vendor2;
- *ecx = env->cpuid_vendor3;
- break;
- case 1:
- *eax = env->cpuid_version;
- *ebx = (cpu->apic_id << 24) |
- 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
- *ecx = env->features[FEAT_1_ECX];
- if ((*ecx & CPUID_EXT_XSAVE) && (env->cr[4] & CR4_OSXSAVE_MASK)) {
- *ecx |= CPUID_EXT_OSXSAVE;
- }
- *edx = env->features[FEAT_1_EDX];
- if (cs->nr_cores * cs->nr_threads > 1) {
- *ebx |= (cs->nr_cores * cs->nr_threads) << 16;
- *edx |= CPUID_HT;
- }
- break;
- case 2:
- /* cache info: needed for Pentium Pro compatibility */
- if (cpu->cache_info_passthrough) {
- host_cpuid(index, 0, eax, ebx, ecx, edx);
- break;
- }
- *eax = 1; /* Number of CPUID[EAX=2] calls required */
- *ebx = 0;
- if (!cpu->enable_l3_cache) {
- *ecx = 0;
- } else {
- *ecx = L3_N_DESCRIPTOR;
- }
- *edx = (L1D_DESCRIPTOR << 16) | \
- (L1I_DESCRIPTOR << 8) | \
- (L2_DESCRIPTOR);
- break;
- case 4:
- /* cache info: needed for Core compatibility */
- if (cpu->cache_info_passthrough) {
- host_cpuid(index, count, eax, ebx, ecx, edx);
- *eax &= ~0xFC000000;
- } else {
- *eax = 0;
- switch (count) {
- case 0: /* L1 dcache info */
- *eax |= CPUID_4_TYPE_DCACHE | \
- CPUID_4_LEVEL(1) | \
- CPUID_4_SELF_INIT_LEVEL;
- *ebx = (L1D_LINE_SIZE - 1) | \
- ((L1D_PARTITIONS - 1) << 12) | \
- ((L1D_ASSOCIATIVITY - 1) << 22);
- *ecx = L1D_SETS - 1;
- *edx = CPUID_4_NO_INVD_SHARING;
- break;
- case 1: /* L1 icache info */
- *eax |= CPUID_4_TYPE_ICACHE | \
- CPUID_4_LEVEL(1) | \
- CPUID_4_SELF_INIT_LEVEL;
- *ebx = (L1I_LINE_SIZE - 1) | \
- ((L1I_PARTITIONS - 1) << 12) | \
- ((L1I_ASSOCIATIVITY - 1) << 22);
- *ecx = L1I_SETS - 1;
- *edx = CPUID_4_NO_INVD_SHARING;
- break;
- case 2: /* L2 cache info */
- *eax |= CPUID_4_TYPE_UNIFIED | \
- CPUID_4_LEVEL(2) | \
- CPUID_4_SELF_INIT_LEVEL;
- if (cs->nr_threads > 1) {
- *eax |= (cs->nr_threads - 1) << 14;
- }
- *ebx = (L2_LINE_SIZE - 1) | \
- ((L2_PARTITIONS - 1) << 12) | \
- ((L2_ASSOCIATIVITY - 1) << 22);
- *ecx = L2_SETS - 1;
- *edx = CPUID_4_NO_INVD_SHARING;
- break;
- case 3: /* L3 cache info */
- if (!cpu->enable_l3_cache) {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- }
- *eax |= CPUID_4_TYPE_UNIFIED | \
- CPUID_4_LEVEL(3) | \
- CPUID_4_SELF_INIT_LEVEL;
- pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);
- *eax |= ((1 << pkg_offset) - 1) << 14;
- *ebx = (L3_N_LINE_SIZE - 1) | \
- ((L3_N_PARTITIONS - 1) << 12) | \
- ((L3_N_ASSOCIATIVITY - 1) << 22);
- *ecx = L3_N_SETS - 1;
- *edx = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX;
- break;
- default: /* end of info */
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- }
- }
-
- /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
- if ((*eax & 31) && cs->nr_cores > 1) {
- *eax |= (cs->nr_cores - 1) << 26;
- }
- break;
- case 5:
- /* mwait info: needed for Core compatibility */
- *eax = 0; /* Smallest monitor-line size in bytes */
- *ebx = 0; /* Largest monitor-line size in bytes */
- *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
- *edx = 0;
- break;
- case 6:
- /* Thermal and Power Leaf */
- *eax = env->features[FEAT_6_EAX];
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- case 7:
- /* Structured Extended Feature Flags Enumeration Leaf */
- if (count == 0) {
- *eax = 0; /* Maximum ECX value for sub-leaves */
- *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
- *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */
- if ((*ecx & CPUID_7_0_ECX_PKU) && env->cr[4] & CR4_PKE_MASK) {
- *ecx |= CPUID_7_0_ECX_OSPKE;
- }
- *edx = env->features[FEAT_7_0_EDX]; /* Feature flags */
- } else {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- }
- break;
- case 9:
- /* Direct Cache Access Information Leaf */
- *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- case 0xA:
- /* Architectural Performance Monitoring Leaf */
- if (kvm_enabled() && cpu->enable_pmu) {
- KVMState *s = cs->kvm_state;
-
- *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
- *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
- *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
- *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
- } else {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- }
- break;
- case 0xB:
- /* Extended Topology Enumeration Leaf */
- if (!cpu->enable_cpuid_0xb) {
- *eax = *ebx = *ecx = *edx = 0;
- break;
- }
-
- *ecx = count & 0xff;
- *edx = cpu->apic_id;
-
- switch (count) {
- case 0:
- *eax = apicid_core_offset(cs->nr_cores, cs->nr_threads);
- *ebx = cs->nr_threads;
- *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
- break;
- case 1:
- *eax = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);
- *ebx = cs->nr_cores * cs->nr_threads;
- *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
- break;
- default:
- *eax = 0;
- *ebx = 0;
- *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;
- }
-
- assert(!(*eax & ~0x1f));
- *ebx &= 0xffff; /* The count doesn't need to be reliable. */
- break;
- case 0xD: {
- /* Processor Extended State */
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
- break;
- }
-
- if (count == 0) {
- *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
- *eax = env->features[FEAT_XSAVE_COMP_LO];
- *edx = env->features[FEAT_XSAVE_COMP_HI];
- *ebx = *ecx;
- } else if (count == 1) {
- *eax = env->features[FEAT_XSAVE];
- } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
- if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
- const ExtSaveArea *esa = &x86_ext_save_areas[count];
- *eax = esa->size;
- *ebx = esa->offset;
- }
- }
- break;
- }
- case 0x80000000:
- *eax = env->cpuid_xlevel;
- *ebx = env->cpuid_vendor1;
- *edx = env->cpuid_vendor2;
- *ecx = env->cpuid_vendor3;
- break;
- case 0x80000001:
- *eax = env->cpuid_version;
- *ebx = 0;
- *ecx = env->features[FEAT_8000_0001_ECX];
- *edx = env->features[FEAT_8000_0001_EDX];
-
- /* The Linux kernel checks for the CMPLegacy bit and
- * discards multiple thread information if it is set.
- * So don't set it here for Intel to make Linux guests happy.
- */
- if (cs->nr_cores * cs->nr_threads > 1) {
- if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||
- env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||
- env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {
- *ecx |= 1 << 1; /* CmpLegacy bit */
- }
- }
- break;
- case 0x80000002:
- case 0x80000003:
- case 0x80000004:
- *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
- *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
- *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
- *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
- break;
- case 0x80000005:
- /* cache info (L1 cache) */
- if (cpu->cache_info_passthrough) {
- host_cpuid(index, 0, eax, ebx, ecx, edx);
- break;
- }
- *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
- (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
- *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
- (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
- *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \
- (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);
- *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \
- (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);
- break;
- case 0x80000006:
- /* cache info (L2 cache) */
- if (cpu->cache_info_passthrough) {
- host_cpuid(index, 0, eax, ebx, ecx, edx);
- break;
- }
- *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
- (L2_DTLB_2M_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
- (L2_ITLB_2M_ENTRIES);
- *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \
- (L2_DTLB_4K_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
- (L2_ITLB_4K_ENTRIES);
- *ecx = (L2_SIZE_KB_AMD << 16) | \
- (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \
- (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);
- if (!cpu->enable_l3_cache) {
- *edx = ((L3_SIZE_KB / 512) << 18) | \
- (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
- (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
- } else {
- *edx = ((L3_N_SIZE_KB_AMD / 512) << 18) | \
- (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \
- (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE);
- }
- break;
- case 0x80000007:
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = env->features[FEAT_8000_0007_EDX];
- break;
- case 0x80000008:
- /* virtual & phys address size in low 2 bytes. */
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
- /* 64 bit processor, 48 bits virtual, configurable
- * physical bits.
- */
- *eax = 0x00003000 + cpu->phys_bits;
- } else {
- *eax = cpu->phys_bits;
- }
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- if (cs->nr_cores * cs->nr_threads > 1) {
- *ecx |= (cs->nr_cores * cs->nr_threads) - 1;
- }
- break;
- case 0x8000000A:
- if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
- *eax = 0x00000001; /* SVM Revision */
- *ebx = 0x00000010; /* nr of ASIDs */
- *ecx = 0;
- *edx = env->features[FEAT_SVM]; /* optional features */
- } else {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- }
- break;
- case 0xC0000000:
- *eax = env->cpuid_xlevel2;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- case 0xC0000001:
- /* Support for VIA CPU's CPUID instruction */
- *eax = env->cpuid_version;
- *ebx = 0;
- *ecx = 0;
- *edx = env->features[FEAT_C000_0001_EDX];
- break;
- case 0xC0000002:
- case 0xC0000003:
- case 0xC0000004:
- /* Reserved for the future, and now filled with zero */
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- default:
- /* reserved values: zero */
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
- break;
- }
-}
-
-/* CPUClass::reset() */
-static void x86_cpu_reset(CPUState *s)
-{
- X86CPU *cpu = X86_CPU(s);
- X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
- CPUX86State *env = &cpu->env;
- target_ulong cr4;
- uint64_t xcr0;
- int i;
-
- xcc->parent_reset(s);
-
- memset(env, 0, offsetof(CPUX86State, end_reset_fields));
-
- tlb_flush(s, 1);
-
- env->old_exception = -1;
-
- /* init to reset state */
-
- env->hflags2 |= HF2_GIF_MASK;
-
- cpu_x86_update_cr0(env, 0x60000010);
- env->a20_mask = ~0x0;
- env->smbase = 0x30000;
-
- env->idt.limit = 0xffff;
- env->gdt.limit = 0xffff;
- env->ldt.limit = 0xffff;
- env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
- env->tr.limit = 0xffff;
- env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
-
- cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
- DESC_R_MASK | DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
-
- env->eip = 0xfff0;
- env->regs[R_EDX] = env->cpuid_version;
-
- env->eflags = 0x2;
-
- /* FPU init */
- for (i = 0; i < 8; i++) {
- env->fptags[i] = 1;
- }
- cpu_set_fpuc(env, 0x37f);
-
- env->mxcsr = 0x1f80;
- /* All units are in INIT state. */
- env->xstate_bv = 0;
-
- env->pat = 0x0007040600070406ULL;
- env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
-
- memset(env->dr, 0, sizeof(env->dr));
- env->dr[6] = DR6_FIXED_1;
- env->dr[7] = DR7_FIXED_1;
- cpu_breakpoint_remove_all(s, BP_CPU);
- cpu_watchpoint_remove_all(s, BP_CPU);
-
- cr4 = 0;
- xcr0 = XSTATE_FP_MASK;
-
-#ifdef CONFIG_USER_ONLY
- /* Enable all the features for user-mode. */
- if (env->features[FEAT_1_EDX] & CPUID_SSE) {
- xcr0 |= XSTATE_SSE_MASK;
- }
- for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
- const ExtSaveArea *esa = &x86_ext_save_areas[i];
- if (env->features[esa->feature] & esa->bits) {
- xcr0 |= 1ull << i;
- }
- }
-
- if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) {
- cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK;
- }
- if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FSGSBASE) {
- cr4 |= CR4_FSGSBASE_MASK;
- }
-#endif
-
- env->xcr0 = xcr0;
- cpu_x86_update_cr4(env, cr4);
-
- /*
- * SDM 11.11.5 requires:
- * - IA32_MTRR_DEF_TYPE MSR.E = 0
- * - IA32_MTRR_PHYSMASKn.V = 0
- * All other bits are undefined. For simplification, zero it all.
- */
- env->mtrr_deftype = 0;
- memset(env->mtrr_var, 0, sizeof(env->mtrr_var));
- memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed));
-
-#if !defined(CONFIG_USER_ONLY)
- /* We hard-wire the BSP to the first CPU. */
- apic_designate_bsp(cpu->apic_state, s->cpu_index == 0);
-
- s->halted = !cpu_is_bsp(cpu);
-
- if (kvm_enabled()) {
- kvm_arch_reset_vcpu(cpu);
- }
-#endif
-}
-
-#ifndef CONFIG_USER_ONLY
-bool cpu_is_bsp(X86CPU *cpu)
-{
- return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
-}
-
-/* TODO: remove me, when reset over QOM tree is implemented */
-static void x86_cpu_machine_reset_cb(void *opaque)
-{
- X86CPU *cpu = opaque;
- cpu_reset(CPU(cpu));
-}
-#endif
-
-static void mce_init(X86CPU *cpu)
-{
- CPUX86State *cenv = &cpu->env;
- unsigned int bank;
-
- if (((cenv->cpuid_version >> 8) & 0xf) >= 6
- && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
- (CPUID_MCE | CPUID_MCA)) {
- cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF |
- (cpu->enable_lmce ? MCG_LMCE_P : 0);
- cenv->mcg_ctl = ~(uint64_t)0;
- for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
- cenv->mce_banks[bank * 4] = ~(uint64_t)0;
- }
- }
-}
-
-#ifndef CONFIG_USER_ONLY
-APICCommonClass *apic_get_class(void)
-{
- const char *apic_type = "apic";
-
- if (kvm_apic_in_kernel()) {
- apic_type = "kvm-apic";
- } else if (xen_enabled()) {
- apic_type = "xen-apic";
- }
-
- return APIC_COMMON_CLASS(object_class_by_name(apic_type));
-}
-
-static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
-{
- APICCommonState *apic;
- ObjectClass *apic_class = OBJECT_CLASS(apic_get_class());
-
- cpu->apic_state = DEVICE(object_new(object_class_get_name(apic_class)));
-
- object_property_add_child(OBJECT(cpu), "lapic",
- OBJECT(cpu->apic_state), &error_abort);
- object_unref(OBJECT(cpu->apic_state));
-
- qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
- /* TODO: convert to link<> */
- apic = APIC_COMMON(cpu->apic_state);
- apic->cpu = cpu;
- apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
-}
-
-static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
-{
- APICCommonState *apic;
- static bool apic_mmio_map_once;
-
- if (cpu->apic_state == NULL) {
- return;
- }
- object_property_set_bool(OBJECT(cpu->apic_state), true, "realized",
- errp);
-
- /* Map APIC MMIO area */
- apic = APIC_COMMON(cpu->apic_state);
- if (!apic_mmio_map_once) {
- memory_region_add_subregion_overlap(get_system_memory(),
- apic->apicbase &
- MSR_IA32_APICBASE_BASE,
- &apic->io_memory,
- 0x1000);
- apic_mmio_map_once = true;
- }
-}
-
-static void x86_cpu_machine_done(Notifier *n, void *unused)
-{
- X86CPU *cpu = container_of(n, X86CPU, machine_done);
- MemoryRegion *smram =
- (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
-
- if (smram) {
- cpu->smram = g_new(MemoryRegion, 1);
- memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
- smram, 0, 1ull << 32);
- memory_region_set_enabled(cpu->smram, false);
- memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->smram, 1);
- }
-}
-#else
-static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
-{
-}
-#endif
-
-/* Note: Only safe for use on x86(-64) hosts */
-static uint32_t x86_host_phys_bits(void)
-{
- uint32_t eax;
- uint32_t host_phys_bits;
-
- host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL);
- if (eax >= 0x80000008) {
- host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL);
- /* Note: According to AMD doc 25481 rev 2.34 they have a field
- * at 23:16 that can specify a maximum physical address bits for
- * the guest that can override this value; but I've not seen
- * anything with that set.
- */
- host_phys_bits = eax & 0xff;
- } else {
- /* It's an odd 64 bit machine that doesn't have the leaf for
- * physical address bits; fall back to 36 that's most older
- * Intel.
- */
- host_phys_bits = 36;
- }
-
- return host_phys_bits;
-}
-
-static void x86_cpu_adjust_level(X86CPU *cpu, uint32_t *min, uint32_t value)
-{
- if (*min < value) {
- *min = value;
- }
-}
-
-/* Increase cpuid_min_{level,xlevel,xlevel2} automatically, if appropriate */
-static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w)
-{
- CPUX86State *env = &cpu->env;
- FeatureWordInfo *fi = &feature_word_info[w];
- uint32_t eax = fi->cpuid_eax;
- uint32_t region = eax & 0xF0000000;
-
- if (!env->features[w]) {
- return;
- }
-
- switch (region) {
- case 0x00000000:
- x86_cpu_adjust_level(cpu, &env->cpuid_min_level, eax);
- break;
- case 0x80000000:
- x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, eax);
- break;
- case 0xC0000000:
- x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel2, eax);
- break;
- }
-}
-
-/* Calculate XSAVE components based on the configured CPU feature flags */
-static void x86_cpu_enable_xsave_components(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- int i;
- uint64_t mask;
-
- if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
- return;
- }
-
- mask = 0;
- for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
- const ExtSaveArea *esa = &x86_ext_save_areas[i];
- if (env->features[esa->feature] & esa->bits) {
- mask |= (1ULL << i);
- }
- }
-
- env->features[FEAT_XSAVE_COMP_LO] = mask;
- env->features[FEAT_XSAVE_COMP_HI] = mask >> 32;
-}
-
-/* Load CPUID data based on configured features */
-static void x86_cpu_load_features(X86CPU *cpu, Error **errp)
-{
- CPUX86State *env = &cpu->env;
- FeatureWord w;
- GList *l;
- Error *local_err = NULL;
-
- /*TODO: cpu->host_features incorrectly overwrites features
- * set using "feat=on|off". Once we fix this, we can convert
- * plus_features & minus_features to global properties
- * inside x86_cpu_parse_featurestr() too.
- */
- if (cpu->host_features) {
- for (w = 0; w < FEATURE_WORDS; w++) {
- env->features[w] =
- x86_cpu_get_supported_feature_word(w, cpu->migratable);
- }
- }
-
- for (l = plus_features; l; l = l->next) {
- const char *prop = l->data;
- object_property_set_bool(OBJECT(cpu), true, prop, &local_err);
- if (local_err) {
- goto out;
- }
- }
-
- for (l = minus_features; l; l = l->next) {
- const char *prop = l->data;
- object_property_set_bool(OBJECT(cpu), false, prop, &local_err);
- if (local_err) {
- goto out;
- }
- }
-
- if (!kvm_enabled() || !cpu->expose_kvm) {
- env->features[FEAT_KVM] = 0;
- }
-
- x86_cpu_enable_xsave_components(cpu);
-
- /* CPUID[EAX=7,ECX=0].EBX always increased level automatically: */
- x86_cpu_adjust_feat_level(cpu, FEAT_7_0_EBX);
- if (cpu->full_cpuid_auto_level) {
- x86_cpu_adjust_feat_level(cpu, FEAT_1_EDX);
- x86_cpu_adjust_feat_level(cpu, FEAT_1_ECX);
- x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX);
- x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX);
- x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX);
- x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX);
- x86_cpu_adjust_feat_level(cpu, FEAT_8000_0007_EDX);
- x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
- x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
- x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
- /* SVM requires CPUID[0x8000000A] */
- if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
- x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
- }
- }
-
- /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
- if (env->cpuid_level == UINT32_MAX) {
- env->cpuid_level = env->cpuid_min_level;
- }
- if (env->cpuid_xlevel == UINT32_MAX) {
- env->cpuid_xlevel = env->cpuid_min_xlevel;
- }
- if (env->cpuid_xlevel2 == UINT32_MAX) {
- env->cpuid_xlevel2 = env->cpuid_min_xlevel2;
- }
-
-out:
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- }
-}
-
-#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
- (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \
- (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3)
-#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \
- (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \
- (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3)
-static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
-{
- CPUState *cs = CPU(dev);
- X86CPU *cpu = X86_CPU(dev);
- X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
- CPUX86State *env = &cpu->env;
- Error *local_err = NULL;
- static bool ht_warned;
-
- if (xcc->kvm_required && !kvm_enabled()) {
- char *name = x86_cpu_class_get_model_name(xcc);
- error_setg(&local_err, "CPU model '%s' requires KVM", name);
- g_free(name);
- goto out;
- }
-
- if (cpu->apic_id == UNASSIGNED_APIC_ID) {
- error_setg(errp, "apic-id property was not initialized properly");
- return;
- }
-
- x86_cpu_load_features(cpu, &local_err);
- if (local_err) {
- goto out;
- }
-
- if (x86_cpu_filter_features(cpu) &&
- (cpu->check_cpuid || cpu->enforce_cpuid)) {
- x86_cpu_report_filtered_features(cpu);
- if (cpu->enforce_cpuid) {
- error_setg(&local_err,
- kvm_enabled() ?
- "Host doesn't support requested features" :
- "TCG doesn't support requested features");
- goto out;
- }
- }
-
- /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
- * CPUID[1].EDX.
- */
- if (IS_AMD_CPU(env)) {
- env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
- env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
- & CPUID_EXT2_AMD_ALIASES);
- }
-
- /* For 64bit systems think about the number of physical bits to present.
- * ideally this should be the same as the host; anything other than matching
- * the host can cause incorrect guest behaviour.
- * QEMU used to pick the magic value of 40 bits that corresponds to
- * consumer AMD devices but nothing else.
- */
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
- if (kvm_enabled()) {
- uint32_t host_phys_bits = x86_host_phys_bits();
- static bool warned;
-
- if (cpu->host_phys_bits) {
- /* The user asked for us to use the host physical bits */
- cpu->phys_bits = host_phys_bits;
- }
-
- /* Print a warning if the user set it to a value that's not the
- * host value.
- */
- if (cpu->phys_bits != host_phys_bits && cpu->phys_bits != 0 &&
- !warned) {
- error_report("Warning: Host physical bits (%u)"
- " does not match phys-bits property (%u)",
- host_phys_bits, cpu->phys_bits);
- warned = true;
- }
-
- if (cpu->phys_bits &&
- (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS ||
- cpu->phys_bits < 32)) {
- error_setg(errp, "phys-bits should be between 32 and %u "
- " (but is %u)",
- TARGET_PHYS_ADDR_SPACE_BITS, cpu->phys_bits);
- return;
- }
- } else {
- if (cpu->phys_bits && cpu->phys_bits != TCG_PHYS_ADDR_BITS) {
- error_setg(errp, "TCG only supports phys-bits=%u",
- TCG_PHYS_ADDR_BITS);
- return;
- }
- }
- /* 0 means it was not explicitly set by the user (or by machine
- * compat_props or by the host code above). In this case, the default
- * is the value used by TCG (40).
- */
- if (cpu->phys_bits == 0) {
- cpu->phys_bits = TCG_PHYS_ADDR_BITS;
- }
- } else {
- /* For 32 bit systems don't use the user set value, but keep
- * phys_bits consistent with what we tell the guest.
- */
- if (cpu->phys_bits != 0) {
- error_setg(errp, "phys-bits is not user-configurable in 32 bit");
- return;
- }
-
- if (env->features[FEAT_1_EDX] & CPUID_PSE36) {
- cpu->phys_bits = 36;
- } else {
- cpu->phys_bits = 32;
- }
- }
- cpu_exec_realizefn(cs, &local_err);
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
-
- if (tcg_enabled()) {
- tcg_x86_init();
- }
-
-#ifndef CONFIG_USER_ONLY
- qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
-
- if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) {
- x86_cpu_apic_create(cpu, &local_err);
- if (local_err != NULL) {
- goto out;
- }
- }
-#endif
-
- mce_init(cpu);
-
-#ifndef CONFIG_USER_ONLY
- if (tcg_enabled()) {
- AddressSpace *newas = g_new(AddressSpace, 1);
-
- cpu->cpu_as_mem = g_new(MemoryRegion, 1);
- cpu->cpu_as_root = g_new(MemoryRegion, 1);
-
- /* Outer container... */
- memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
- memory_region_set_enabled(cpu->cpu_as_root, true);
-
- /* ... with two regions inside: normal system memory with low
- * priority, and...
- */
- memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
- get_system_memory(), 0, ~0ull);
- memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
- memory_region_set_enabled(cpu->cpu_as_mem, true);
- address_space_init(newas, cpu->cpu_as_root, "CPU");
- cs->num_ases = 1;
- cpu_address_space_init(cs, newas, 0);
-
- /* ... SMRAM with higher priority, linked from /machine/smram. */
- cpu->machine_done.notify = x86_cpu_machine_done;
- qemu_add_machine_init_done_notifier(&cpu->machine_done);
- }
-#endif
-
- qemu_init_vcpu(cs);
-
- /* Only Intel CPUs support hyperthreading. Even though QEMU fixes this
- * issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX
- * based on inputs (sockets,cores,threads), it is still better to gives
- * users a warning.
- *
- * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise
- * cs->nr_threads hasn't be populated yet and the checking is incorrect.
- */
- if (!IS_INTEL_CPU(env) && cs->nr_threads > 1 && !ht_warned) {
- error_report("AMD CPU doesn't support hyperthreading. Please configure"
- " -smp options properly.");
- ht_warned = true;
- }
-
- x86_cpu_apic_realize(cpu, &local_err);
- if (local_err != NULL) {
- goto out;
- }
- cpu_reset(cs);
-
- xcc->parent_realize(dev, &local_err);
-
-out:
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
-{
- X86CPU *cpu = X86_CPU(dev);
- X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
- Error *local_err = NULL;
-
-#ifndef CONFIG_USER_ONLY
- cpu_remove_sync(CPU(dev));
- qemu_unregister_reset(x86_cpu_machine_reset_cb, dev);
-#endif
-
- if (cpu->apic_state) {
- object_unparent(OBJECT(cpu->apic_state));
- cpu->apic_state = NULL;
- }
-
- xcc->parent_unrealize(dev, &local_err);
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-typedef struct BitProperty {
- uint32_t *ptr;
- uint32_t mask;
-} BitProperty;
-
-static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- BitProperty *fp = opaque;
- bool value = (*fp->ptr & fp->mask) == fp->mask;
- visit_type_bool(v, name, &value, errp);
-}
-
-static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- BitProperty *fp = opaque;
- Error *local_err = NULL;
- bool value;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- visit_type_bool(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- if (value) {
- *fp->ptr |= fp->mask;
- } else {
- *fp->ptr &= ~fp->mask;
- }
-}
-
-static void x86_cpu_release_bit_prop(Object *obj, const char *name,
- void *opaque)
-{
- BitProperty *prop = opaque;
- g_free(prop);
-}
-
-/* Register a boolean property to get/set a single bit in a uint32_t field.
- *
- * The same property name can be registered multiple times to make it affect
- * multiple bits in the same FeatureWord. In that case, the getter will return
- * true only if all bits are set.
- */
-static void x86_cpu_register_bit_prop(X86CPU *cpu,
- const char *prop_name,
- uint32_t *field,
- int bitnr)
-{
- BitProperty *fp;
- ObjectProperty *op;
- uint32_t mask = (1UL << bitnr);
-
- op = object_property_find(OBJECT(cpu), prop_name, NULL);
- if (op) {
- fp = op->opaque;
- assert(fp->ptr == field);
- fp->mask |= mask;
- } else {
- fp = g_new0(BitProperty, 1);
- fp->ptr = field;
- fp->mask = mask;
- object_property_add(OBJECT(cpu), prop_name, "bool",
- x86_cpu_get_bit_prop,
- x86_cpu_set_bit_prop,
- x86_cpu_release_bit_prop, fp, &error_abort);
- }
-}
-
-static void x86_cpu_register_feature_bit_props(X86CPU *cpu,
- FeatureWord w,
- int bitnr)
-{
- FeatureWordInfo *fi = &feature_word_info[w];
- const char *name = fi->feat_names[bitnr];
-
- if (!name) {
- return;
- }
-
- /* Property names should use "-" instead of "_".
- * Old names containing underscores are registered as aliases
- * using object_property_add_alias()
- */
- assert(!strchr(name, '_'));
- /* aliases don't use "|" delimiters anymore, they are registered
- * manually using object_property_add_alias() */
- assert(!strchr(name, '|'));
- x86_cpu_register_bit_prop(cpu, name, &cpu->env.features[w], bitnr);
-}
-
-static void x86_cpu_initfn(Object *obj)
-{
- CPUState *cs = CPU(obj);
- X86CPU *cpu = X86_CPU(obj);
- X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
- CPUX86State *env = &cpu->env;
- FeatureWord w;
-
- cs->env_ptr = env;
-
- object_property_add(obj, "family", "int",
- x86_cpuid_version_get_family,
- x86_cpuid_version_set_family, NULL, NULL, NULL);
- object_property_add(obj, "model", "int",
- x86_cpuid_version_get_model,
- x86_cpuid_version_set_model, NULL, NULL, NULL);
- object_property_add(obj, "stepping", "int",
- x86_cpuid_version_get_stepping,
- x86_cpuid_version_set_stepping, NULL, NULL, NULL);
- object_property_add_str(obj, "vendor",
- x86_cpuid_get_vendor,
- x86_cpuid_set_vendor, NULL);
- object_property_add_str(obj, "model-id",
- x86_cpuid_get_model_id,
- x86_cpuid_set_model_id, NULL);
- object_property_add(obj, "tsc-frequency", "int",
- x86_cpuid_get_tsc_freq,
- x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
- object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo",
- x86_cpu_get_feature_words,
- NULL, NULL, (void *)env->features, NULL);
- object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo",
- x86_cpu_get_feature_words,
- NULL, NULL, (void *)cpu->filtered_features, NULL);
-
- cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
-
- for (w = 0; w < FEATURE_WORDS; w++) {
- int bitnr;
-
- for (bitnr = 0; bitnr < 32; bitnr++) {
- x86_cpu_register_feature_bit_props(cpu, w, bitnr);
- }
- }
-
- object_property_add_alias(obj, "sse3", obj, "pni", &error_abort);
- object_property_add_alias(obj, "pclmuldq", obj, "pclmulqdq", &error_abort);
- object_property_add_alias(obj, "sse4-1", obj, "sse4.1", &error_abort);
- object_property_add_alias(obj, "sse4-2", obj, "sse4.2", &error_abort);
- object_property_add_alias(obj, "xd", obj, "nx", &error_abort);
- object_property_add_alias(obj, "ffxsr", obj, "fxsr-opt", &error_abort);
- object_property_add_alias(obj, "i64", obj, "lm", &error_abort);
-
- object_property_add_alias(obj, "ds_cpl", obj, "ds-cpl", &error_abort);
- object_property_add_alias(obj, "tsc_adjust", obj, "tsc-adjust", &error_abort);
- object_property_add_alias(obj, "fxsr_opt", obj, "fxsr-opt", &error_abort);
- object_property_add_alias(obj, "lahf_lm", obj, "lahf-lm", &error_abort);
- object_property_add_alias(obj, "cmp_legacy", obj, "cmp-legacy", &error_abort);
- object_property_add_alias(obj, "nodeid_msr", obj, "nodeid-msr", &error_abort);
- object_property_add_alias(obj, "perfctr_core", obj, "perfctr-core", &error_abort);
- object_property_add_alias(obj, "perfctr_nb", obj, "perfctr-nb", &error_abort);
- object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay", &error_abort);
- object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu", &error_abort);
- object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf", &error_abort);
- object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time", &error_abort);
- object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi", &error_abort);
- object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt", &error_abort);
- object_property_add_alias(obj, "svm_lock", obj, "svm-lock", &error_abort);
- object_property_add_alias(obj, "nrip_save", obj, "nrip-save", &error_abort);
- object_property_add_alias(obj, "tsc_scale", obj, "tsc-scale", &error_abort);
- object_property_add_alias(obj, "vmcb_clean", obj, "vmcb-clean", &error_abort);
- object_property_add_alias(obj, "pause_filter", obj, "pause-filter", &error_abort);
- object_property_add_alias(obj, "sse4_1", obj, "sse4.1", &error_abort);
- object_property_add_alias(obj, "sse4_2", obj, "sse4.2", &error_abort);
-
- x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
-}
-
-static int64_t x86_cpu_get_arch_id(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- return cpu->apic_id;
-}
-
-static bool x86_cpu_get_paging_enabled(const CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- return cpu->env.cr[0] & CR0_PG_MASK;
-}
-
-static void x86_cpu_set_pc(CPUState *cs, vaddr value)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- cpu->env.eip = value;
-}
-
-static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
-{
- X86CPU *cpu = X86_CPU(cs);
-
- cpu->env.eip = tb->pc - tb->cs_base;
-}
-
-static bool x86_cpu_has_work(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
- CPU_INTERRUPT_POLL)) &&
- (env->eflags & IF_MASK)) ||
- (cs->interrupt_request & (CPU_INTERRUPT_NMI |
- CPU_INTERRUPT_INIT |
- CPU_INTERRUPT_SIPI |
- CPU_INTERRUPT_MCE)) ||
- ((cs->interrupt_request & CPU_INTERRUPT_SMI) &&
- !(env->hflags & HF_SMM_MASK));
-}
-
-static Property x86_cpu_properties[] = {
-#ifdef CONFIG_USER_ONLY
- /* apic_id = 0 by default for *-user, see commit 9886e834 */
- DEFINE_PROP_UINT32("apic-id", X86CPU, apic_id, 0),
- DEFINE_PROP_INT32("thread-id", X86CPU, thread_id, 0),
- DEFINE_PROP_INT32("core-id", X86CPU, core_id, 0),
- DEFINE_PROP_INT32("socket-id", X86CPU, socket_id, 0),
-#else
- DEFINE_PROP_UINT32("apic-id", X86CPU, apic_id, UNASSIGNED_APIC_ID),
- DEFINE_PROP_INT32("thread-id", X86CPU, thread_id, -1),
- DEFINE_PROP_INT32("core-id", X86CPU, core_id, -1),
- DEFINE_PROP_INT32("socket-id", X86CPU, socket_id, -1),
-#endif
- DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
- { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks },
- DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
- DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
- DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
- DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
- DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
- DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
- DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
- DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
- DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
- DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
- DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
- DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
- DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0),
- DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),
- DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true),
- DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX),
- DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, UINT32_MAX),
- DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, UINT32_MAX),
- DEFINE_PROP_UINT32("min-level", X86CPU, env.cpuid_min_level, 0),
- DEFINE_PROP_UINT32("min-xlevel", X86CPU, env.cpuid_min_xlevel, 0),
- DEFINE_PROP_UINT32("min-xlevel2", X86CPU, env.cpuid_min_xlevel2, 0),
- DEFINE_PROP_BOOL("full-cpuid-auto-level", X86CPU, full_cpuid_auto_level, true),
- DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
- DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
- DEFINE_PROP_BOOL("lmce", X86CPU, enable_lmce, false),
- DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
- DEFINE_PROP_END_OF_LIST()
-};
-
-static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
-{
- X86CPUClass *xcc = X86_CPU_CLASS(oc);
- CPUClass *cc = CPU_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- xcc->parent_realize = dc->realize;
- xcc->parent_unrealize = dc->unrealize;
- dc->realize = x86_cpu_realizefn;
- dc->unrealize = x86_cpu_unrealizefn;
- dc->props = x86_cpu_properties;
-
- xcc->parent_reset = cc->reset;
- cc->reset = x86_cpu_reset;
- cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
-
- cc->class_by_name = x86_cpu_class_by_name;
- cc->parse_features = x86_cpu_parse_featurestr;
- cc->has_work = x86_cpu_has_work;
- cc->do_interrupt = x86_cpu_do_interrupt;
- cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
- cc->dump_state = x86_cpu_dump_state;
- cc->set_pc = x86_cpu_set_pc;
- cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
- cc->gdb_read_register = x86_cpu_gdb_read_register;
- cc->gdb_write_register = x86_cpu_gdb_write_register;
- cc->get_arch_id = x86_cpu_get_arch_id;
- cc->get_paging_enabled = x86_cpu_get_paging_enabled;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = x86_cpu_handle_mmu_fault;
-#else
- cc->get_memory_mapping = x86_cpu_get_memory_mapping;
- cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
- cc->write_elf64_note = x86_cpu_write_elf64_note;
- cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
- cc->write_elf32_note = x86_cpu_write_elf32_note;
- cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
- cc->vmsd = &vmstate_x86_cpu;
-#endif
- /* CPU_NB_REGS * 2 = general regs + xmm regs
- * 25 = eip, eflags, 6 seg regs, st[0-7], fctrl,...,fop, mxcsr.
- */
- cc->gdb_num_core_regs = CPU_NB_REGS * 2 + 25;
-#ifndef CONFIG_USER_ONLY
- cc->debug_excp_handler = breakpoint_handler;
-#endif
- cc->cpu_exec_enter = x86_cpu_exec_enter;
- cc->cpu_exec_exit = x86_cpu_exec_exit;
-
- dc->cannot_instantiate_with_device_add_yet = false;
-}
-
-static const TypeInfo x86_cpu_type_info = {
- .name = TYPE_X86_CPU,
- .parent = TYPE_CPU,
- .instance_size = sizeof(X86CPU),
- .instance_init = x86_cpu_initfn,
- .abstract = true,
- .class_size = sizeof(X86CPUClass),
- .class_init = x86_cpu_common_class_init,
-};
-
-static void x86_cpu_register_types(void)
-{
- int i;
-
- type_register_static(&x86_cpu_type_info);
- for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
- x86_register_cpudef_type(&builtin_x86_defs[i]);
- }
-#ifdef CONFIG_KVM
- type_register_static(&host_x86_cpu_type_info);
-#endif
-}
-
-type_init(x86_cpu_register_types)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
deleted file mode 100644
index c605724022..0000000000
--- a/target-i386/cpu.h
+++ /dev/null
@@ -1,1656 +0,0 @@
-/*
- * i386 virtual CPU header
- *
- * 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/>.
- */
-
-#ifndef I386_CPU_H
-#define I386_CPU_H
-
-#include "qemu-common.h"
-#include "cpu-qom.h"
-#include "standard-headers/asm-x86/hyperv.h"
-
-#ifdef TARGET_X86_64
-#define TARGET_LONG_BITS 64
-#else
-#define TARGET_LONG_BITS 32
-#endif
-
-/* Maximum instruction code size */
-#define TARGET_MAX_INSN_SIZE 16
-
-/* support for self modifying code even if the modified instruction is
- close to the modifying instruction */
-#define TARGET_HAS_PRECISE_SMC
-
-#ifdef TARGET_X86_64
-#define I386_ELF_MACHINE EM_X86_64
-#define ELF_MACHINE_UNAME "x86_64"
-#else
-#define I386_ELF_MACHINE EM_386
-#define ELF_MACHINE_UNAME "i686"
-#endif
-
-#define CPUArchState struct CPUX86State
-
-#include "exec/cpu-defs.h"
-
-#include "fpu/softfloat.h"
-
-#define R_EAX 0
-#define R_ECX 1
-#define R_EDX 2
-#define R_EBX 3
-#define R_ESP 4
-#define R_EBP 5
-#define R_ESI 6
-#define R_EDI 7
-
-#define R_AL 0
-#define R_CL 1
-#define R_DL 2
-#define R_BL 3
-#define R_AH 4
-#define R_CH 5
-#define R_DH 6
-#define R_BH 7
-
-#define R_ES 0
-#define R_CS 1
-#define R_SS 2
-#define R_DS 3
-#define R_FS 4
-#define R_GS 5
-
-/* segment descriptor fields */
-#define DESC_G_MASK (1 << 23)
-#define DESC_B_SHIFT 22
-#define DESC_B_MASK (1 << DESC_B_SHIFT)
-#define DESC_L_SHIFT 21 /* x86_64 only : 64 bit code segment */
-#define DESC_L_MASK (1 << DESC_L_SHIFT)
-#define DESC_AVL_MASK (1 << 20)
-#define DESC_P_MASK (1 << 15)
-#define DESC_DPL_SHIFT 13
-#define DESC_DPL_MASK (3 << DESC_DPL_SHIFT)
-#define DESC_S_MASK (1 << 12)
-#define DESC_TYPE_SHIFT 8
-#define DESC_TYPE_MASK (15 << DESC_TYPE_SHIFT)
-#define DESC_A_MASK (1 << 8)
-
-#define DESC_CS_MASK (1 << 11) /* 1=code segment 0=data segment */
-#define DESC_C_MASK (1 << 10) /* code: conforming */
-#define DESC_R_MASK (1 << 9) /* code: readable */
-
-#define DESC_E_MASK (1 << 10) /* data: expansion direction */
-#define DESC_W_MASK (1 << 9) /* data: writable */
-
-#define DESC_TSS_BUSY_MASK (1 << 9)
-
-/* eflags masks */
-#define CC_C 0x0001
-#define CC_P 0x0004
-#define CC_A 0x0010
-#define CC_Z 0x0040
-#define CC_S 0x0080
-#define CC_O 0x0800
-
-#define TF_SHIFT 8
-#define IOPL_SHIFT 12
-#define VM_SHIFT 17
-
-#define TF_MASK 0x00000100
-#define IF_MASK 0x00000200
-#define DF_MASK 0x00000400
-#define IOPL_MASK 0x00003000
-#define NT_MASK 0x00004000
-#define RF_MASK 0x00010000
-#define VM_MASK 0x00020000
-#define AC_MASK 0x00040000
-#define VIF_MASK 0x00080000
-#define VIP_MASK 0x00100000
-#define ID_MASK 0x00200000
-
-/* hidden flags - used internally by qemu to represent additional cpu
- states. Only the INHIBIT_IRQ, SMM and SVMI are not redundant. We
- avoid using the IOPL_MASK, TF_MASK, VM_MASK and AC_MASK bit
- positions to ease oring with eflags. */
-/* current cpl */
-#define HF_CPL_SHIFT 0
-/* true if hardware interrupts must be disabled for next instruction */
-#define HF_INHIBIT_IRQ_SHIFT 3
-/* 16 or 32 segments */
-#define HF_CS32_SHIFT 4
-#define HF_SS32_SHIFT 5
-/* zero base for DS, ES and SS : can be '0' only in 32 bit CS segment */
-#define HF_ADDSEG_SHIFT 6
-/* copy of CR0.PE (protected mode) */
-#define HF_PE_SHIFT 7
-#define HF_TF_SHIFT 8 /* must be same as eflags */
-#define HF_MP_SHIFT 9 /* the order must be MP, EM, TS */
-#define HF_EM_SHIFT 10
-#define HF_TS_SHIFT 11
-#define HF_IOPL_SHIFT 12 /* must be same as eflags */
-#define HF_LMA_SHIFT 14 /* only used on x86_64: long mode active */
-#define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment */
-#define HF_RF_SHIFT 16 /* must be same as eflags */
-#define HF_VM_SHIFT 17 /* must be same as eflags */
-#define HF_AC_SHIFT 18 /* must be same as eflags */
-#define HF_SMM_SHIFT 19 /* CPU in SMM mode */
-#define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */
-#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */
-#define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */
-#define HF_SMAP_SHIFT 23 /* CR4.SMAP */
-#define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */
-#define HF_MPX_EN_SHIFT 25 /* MPX Enabled (CR4+XCR0+BNDCFGx) */
-#define HF_MPX_IU_SHIFT 26 /* BND registers in-use */
-
-#define HF_CPL_MASK (3 << HF_CPL_SHIFT)
-#define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT)
-#define HF_CS32_MASK (1 << HF_CS32_SHIFT)
-#define HF_SS32_MASK (1 << HF_SS32_SHIFT)
-#define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT)
-#define HF_PE_MASK (1 << HF_PE_SHIFT)
-#define HF_TF_MASK (1 << HF_TF_SHIFT)
-#define HF_MP_MASK (1 << HF_MP_SHIFT)
-#define HF_EM_MASK (1 << HF_EM_SHIFT)
-#define HF_TS_MASK (1 << HF_TS_SHIFT)
-#define HF_IOPL_MASK (3 << HF_IOPL_SHIFT)
-#define HF_LMA_MASK (1 << HF_LMA_SHIFT)
-#define HF_CS64_MASK (1 << HF_CS64_SHIFT)
-#define HF_RF_MASK (1 << HF_RF_SHIFT)
-#define HF_VM_MASK (1 << HF_VM_SHIFT)
-#define HF_AC_MASK (1 << HF_AC_SHIFT)
-#define HF_SMM_MASK (1 << HF_SMM_SHIFT)
-#define HF_SVME_MASK (1 << HF_SVME_SHIFT)
-#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT)
-#define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
-#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT)
-#define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT)
-#define HF_MPX_EN_MASK (1 << HF_MPX_EN_SHIFT)
-#define HF_MPX_IU_MASK (1 << HF_MPX_IU_SHIFT)
-
-/* hflags2 */
-
-#define HF2_GIF_SHIFT 0 /* if set CPU takes interrupts */
-#define HF2_HIF_SHIFT 1 /* value of IF_MASK when entering SVM */
-#define HF2_NMI_SHIFT 2 /* CPU serving NMI */
-#define HF2_VINTR_SHIFT 3 /* value of V_INTR_MASKING bit */
-#define HF2_SMM_INSIDE_NMI_SHIFT 4 /* CPU serving SMI nested inside NMI */
-#define HF2_MPX_PR_SHIFT 5 /* BNDCFGx.BNDPRESERVE */
-
-#define HF2_GIF_MASK (1 << HF2_GIF_SHIFT)
-#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
-#define HF2_NMI_MASK (1 << HF2_NMI_SHIFT)
-#define HF2_VINTR_MASK (1 << HF2_VINTR_SHIFT)
-#define HF2_SMM_INSIDE_NMI_MASK (1 << HF2_SMM_INSIDE_NMI_SHIFT)
-#define HF2_MPX_PR_MASK (1 << HF2_MPX_PR_SHIFT)
-
-#define CR0_PE_SHIFT 0
-#define CR0_MP_SHIFT 1
-
-#define CR0_PE_MASK (1U << 0)
-#define CR0_MP_MASK (1U << 1)
-#define CR0_EM_MASK (1U << 2)
-#define CR0_TS_MASK (1U << 3)
-#define CR0_ET_MASK (1U << 4)
-#define CR0_NE_MASK (1U << 5)
-#define CR0_WP_MASK (1U << 16)
-#define CR0_AM_MASK (1U << 18)
-#define CR0_PG_MASK (1U << 31)
-
-#define CR4_VME_MASK (1U << 0)
-#define CR4_PVI_MASK (1U << 1)
-#define CR4_TSD_MASK (1U << 2)
-#define CR4_DE_MASK (1U << 3)
-#define CR4_PSE_MASK (1U << 4)
-#define CR4_PAE_MASK (1U << 5)
-#define CR4_MCE_MASK (1U << 6)
-#define CR4_PGE_MASK (1U << 7)
-#define CR4_PCE_MASK (1U << 8)
-#define CR4_OSFXSR_SHIFT 9
-#define CR4_OSFXSR_MASK (1U << CR4_OSFXSR_SHIFT)
-#define CR4_OSXMMEXCPT_MASK (1U << 10)
-#define CR4_VMXE_MASK (1U << 13)
-#define CR4_SMXE_MASK (1U << 14)
-#define CR4_FSGSBASE_MASK (1U << 16)
-#define CR4_PCIDE_MASK (1U << 17)
-#define CR4_OSXSAVE_MASK (1U << 18)
-#define CR4_SMEP_MASK (1U << 20)
-#define CR4_SMAP_MASK (1U << 21)
-#define CR4_PKE_MASK (1U << 22)
-
-#define DR6_BD (1 << 13)
-#define DR6_BS (1 << 14)
-#define DR6_BT (1 << 15)
-#define DR6_FIXED_1 0xffff0ff0
-
-#define DR7_GD (1 << 13)
-#define DR7_TYPE_SHIFT 16
-#define DR7_LEN_SHIFT 18
-#define DR7_FIXED_1 0x00000400
-#define DR7_GLOBAL_BP_MASK 0xaa
-#define DR7_LOCAL_BP_MASK 0x55
-#define DR7_MAX_BP 4
-#define DR7_TYPE_BP_INST 0x0
-#define DR7_TYPE_DATA_WR 0x1
-#define DR7_TYPE_IO_RW 0x2
-#define DR7_TYPE_DATA_RW 0x3
-
-#define PG_PRESENT_BIT 0
-#define PG_RW_BIT 1
-#define PG_USER_BIT 2
-#define PG_PWT_BIT 3
-#define PG_PCD_BIT 4
-#define PG_ACCESSED_BIT 5
-#define PG_DIRTY_BIT 6
-#define PG_PSE_BIT 7
-#define PG_GLOBAL_BIT 8
-#define PG_PSE_PAT_BIT 12
-#define PG_PKRU_BIT 59
-#define PG_NX_BIT 63
-
-#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
-#define PG_RW_MASK (1 << PG_RW_BIT)
-#define PG_USER_MASK (1 << PG_USER_BIT)
-#define PG_PWT_MASK (1 << PG_PWT_BIT)
-#define PG_PCD_MASK (1 << PG_PCD_BIT)
-#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
-#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
-#define PG_PSE_MASK (1 << PG_PSE_BIT)
-#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
-#define PG_PSE_PAT_MASK (1 << PG_PSE_PAT_BIT)
-#define PG_ADDRESS_MASK 0x000ffffffffff000LL
-#define PG_HI_RSVD_MASK (PG_ADDRESS_MASK & ~PHYS_ADDR_MASK)
-#define PG_HI_USER_MASK 0x7ff0000000000000LL
-#define PG_PKRU_MASK (15ULL << PG_PKRU_BIT)
-#define PG_NX_MASK (1ULL << PG_NX_BIT)
-
-#define PG_ERROR_W_BIT 1
-
-#define PG_ERROR_P_MASK 0x01
-#define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT)
-#define PG_ERROR_U_MASK 0x04
-#define PG_ERROR_RSVD_MASK 0x08
-#define PG_ERROR_I_D_MASK 0x10
-#define PG_ERROR_PK_MASK 0x20
-
-#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
-#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
-#define MCG_LMCE_P (1ULL<<27) /* Local Machine Check Supported */
-
-#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
-#define MCE_BANKS_DEF 10
-
-#define MCG_CAP_BANKS_MASK 0xff
-
-#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */
-#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */
-#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */
-#define MCG_STATUS_LMCE (1ULL<<3) /* Local MCE signaled */
-
-#define MCG_EXT_CTL_LMCE_EN (1ULL<<0) /* Local MCE enabled */
-
-#define MCI_STATUS_VAL (1ULL<<63) /* valid error */
-#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */
-#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */
-#define MCI_STATUS_EN (1ULL<<60) /* error enabled */
-#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */
-#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */
-#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */
-#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
-#define MCI_STATUS_AR (1ULL<<55) /* Action required */
-
-/* MISC register defines */
-#define MCM_ADDR_SEGOFF 0 /* segment offset */
-#define MCM_ADDR_LINEAR 1 /* linear address */
-#define MCM_ADDR_PHYS 2 /* physical address */
-#define MCM_ADDR_MEM 3 /* memory address */
-#define MCM_ADDR_GENERIC 7 /* generic */
-
-#define MSR_IA32_TSC 0x10
-#define MSR_IA32_APICBASE 0x1b
-#define MSR_IA32_APICBASE_BSP (1<<8)
-#define MSR_IA32_APICBASE_ENABLE (1<<11)
-#define MSR_IA32_APICBASE_EXTD (1 << 10)
-#define MSR_IA32_APICBASE_BASE (0xfffffU<<12)
-#define MSR_IA32_FEATURE_CONTROL 0x0000003a
-#define MSR_TSC_ADJUST 0x0000003b
-#define MSR_IA32_TSCDEADLINE 0x6e0
-
-#define FEATURE_CONTROL_LOCKED (1<<0)
-#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
-#define FEATURE_CONTROL_LMCE (1<<20)
-
-#define MSR_P6_PERFCTR0 0xc1
-
-#define MSR_IA32_SMBASE 0x9e
-#define MSR_MTRRcap 0xfe
-#define MSR_MTRRcap_VCNT 8
-#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8)
-#define MSR_MTRRcap_WC_SUPPORTED (1 << 10)
-
-#define MSR_IA32_SYSENTER_CS 0x174
-#define MSR_IA32_SYSENTER_ESP 0x175
-#define MSR_IA32_SYSENTER_EIP 0x176
-
-#define MSR_MCG_CAP 0x179
-#define MSR_MCG_STATUS 0x17a
-#define MSR_MCG_CTL 0x17b
-#define MSR_MCG_EXT_CTL 0x4d0
-
-#define MSR_P6_EVNTSEL0 0x186
-
-#define MSR_IA32_PERF_STATUS 0x198
-
-#define MSR_IA32_MISC_ENABLE 0x1a0
-/* Indicates good rep/movs microcode on some processors: */
-#define MSR_IA32_MISC_ENABLE_DEFAULT 1
-
-#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg))
-#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1)
-
-#define MSR_MTRRphysIndex(addr) ((((addr) & ~1u) - 0x200) / 2)
-
-#define MSR_MTRRfix64K_00000 0x250
-#define MSR_MTRRfix16K_80000 0x258
-#define MSR_MTRRfix16K_A0000 0x259
-#define MSR_MTRRfix4K_C0000 0x268
-#define MSR_MTRRfix4K_C8000 0x269
-#define MSR_MTRRfix4K_D0000 0x26a
-#define MSR_MTRRfix4K_D8000 0x26b
-#define MSR_MTRRfix4K_E0000 0x26c
-#define MSR_MTRRfix4K_E8000 0x26d
-#define MSR_MTRRfix4K_F0000 0x26e
-#define MSR_MTRRfix4K_F8000 0x26f
-
-#define MSR_PAT 0x277
-
-#define MSR_MTRRdefType 0x2ff
-
-#define MSR_CORE_PERF_FIXED_CTR0 0x309
-#define MSR_CORE_PERF_FIXED_CTR1 0x30a
-#define MSR_CORE_PERF_FIXED_CTR2 0x30b
-#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x38d
-#define MSR_CORE_PERF_GLOBAL_STATUS 0x38e
-#define MSR_CORE_PERF_GLOBAL_CTRL 0x38f
-#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x390
-
-#define MSR_MC0_CTL 0x400
-#define MSR_MC0_STATUS 0x401
-#define MSR_MC0_ADDR 0x402
-#define MSR_MC0_MISC 0x403
-
-#define MSR_EFER 0xc0000080
-
-#define MSR_EFER_SCE (1 << 0)
-#define MSR_EFER_LME (1 << 8)
-#define MSR_EFER_LMA (1 << 10)
-#define MSR_EFER_NXE (1 << 11)
-#define MSR_EFER_SVME (1 << 12)
-#define MSR_EFER_FFXSR (1 << 14)
-
-#define MSR_STAR 0xc0000081
-#define MSR_LSTAR 0xc0000082
-#define MSR_CSTAR 0xc0000083
-#define MSR_FMASK 0xc0000084
-#define MSR_FSBASE 0xc0000100
-#define MSR_GSBASE 0xc0000101
-#define MSR_KERNELGSBASE 0xc0000102
-#define MSR_TSC_AUX 0xc0000103
-
-#define MSR_VM_HSAVE_PA 0xc0010117
-
-#define MSR_IA32_BNDCFGS 0x00000d90
-#define MSR_IA32_XSS 0x00000da0
-
-#define XSTATE_FP_BIT 0
-#define XSTATE_SSE_BIT 1
-#define XSTATE_YMM_BIT 2
-#define XSTATE_BNDREGS_BIT 3
-#define XSTATE_BNDCSR_BIT 4
-#define XSTATE_OPMASK_BIT 5
-#define XSTATE_ZMM_Hi256_BIT 6
-#define XSTATE_Hi16_ZMM_BIT 7
-#define XSTATE_PKRU_BIT 9
-
-#define XSTATE_FP_MASK (1ULL << XSTATE_FP_BIT)
-#define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
-#define XSTATE_YMM_MASK (1ULL << XSTATE_YMM_BIT)
-#define XSTATE_BNDREGS_MASK (1ULL << XSTATE_BNDREGS_BIT)
-#define XSTATE_BNDCSR_MASK (1ULL << XSTATE_BNDCSR_BIT)
-#define XSTATE_OPMASK_MASK (1ULL << XSTATE_OPMASK_BIT)
-#define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT)
-#define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT)
-#define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT)
-
-/* CPUID feature words */
-typedef enum FeatureWord {
- FEAT_1_EDX, /* CPUID[1].EDX */
- FEAT_1_ECX, /* CPUID[1].ECX */
- FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */
- FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */
- FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */
- FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
- FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
- FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
- FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
- FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
- FEAT_HYPERV_EAX, /* CPUID[4000_0003].EAX */
- FEAT_HYPERV_EBX, /* CPUID[4000_0003].EBX */
- FEAT_HYPERV_EDX, /* CPUID[4000_0003].EDX */
- FEAT_SVM, /* CPUID[8000_000A].EDX */
- FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */
- FEAT_6_EAX, /* CPUID[6].EAX */
- FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
- FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
- FEATURE_WORDS,
-} FeatureWord;
-
-typedef uint32_t FeatureWordArray[FEATURE_WORDS];
-
-/* cpuid_features bits */
-#define CPUID_FP87 (1U << 0)
-#define CPUID_VME (1U << 1)
-#define CPUID_DE (1U << 2)
-#define CPUID_PSE (1U << 3)
-#define CPUID_TSC (1U << 4)
-#define CPUID_MSR (1U << 5)
-#define CPUID_PAE (1U << 6)
-#define CPUID_MCE (1U << 7)
-#define CPUID_CX8 (1U << 8)
-#define CPUID_APIC (1U << 9)
-#define CPUID_SEP (1U << 11) /* sysenter/sysexit */
-#define CPUID_MTRR (1U << 12)
-#define CPUID_PGE (1U << 13)
-#define CPUID_MCA (1U << 14)
-#define CPUID_CMOV (1U << 15)
-#define CPUID_PAT (1U << 16)
-#define CPUID_PSE36 (1U << 17)
-#define CPUID_PN (1U << 18)
-#define CPUID_CLFLUSH (1U << 19)
-#define CPUID_DTS (1U << 21)
-#define CPUID_ACPI (1U << 22)
-#define CPUID_MMX (1U << 23)
-#define CPUID_FXSR (1U << 24)
-#define CPUID_SSE (1U << 25)
-#define CPUID_SSE2 (1U << 26)
-#define CPUID_SS (1U << 27)
-#define CPUID_HT (1U << 28)
-#define CPUID_TM (1U << 29)
-#define CPUID_IA64 (1U << 30)
-#define CPUID_PBE (1U << 31)
-
-#define CPUID_EXT_SSE3 (1U << 0)
-#define CPUID_EXT_PCLMULQDQ (1U << 1)
-#define CPUID_EXT_DTES64 (1U << 2)
-#define CPUID_EXT_MONITOR (1U << 3)
-#define CPUID_EXT_DSCPL (1U << 4)
-#define CPUID_EXT_VMX (1U << 5)
-#define CPUID_EXT_SMX (1U << 6)
-#define CPUID_EXT_EST (1U << 7)
-#define CPUID_EXT_TM2 (1U << 8)
-#define CPUID_EXT_SSSE3 (1U << 9)
-#define CPUID_EXT_CID (1U << 10)
-#define CPUID_EXT_FMA (1U << 12)
-#define CPUID_EXT_CX16 (1U << 13)
-#define CPUID_EXT_XTPR (1U << 14)
-#define CPUID_EXT_PDCM (1U << 15)
-#define CPUID_EXT_PCID (1U << 17)
-#define CPUID_EXT_DCA (1U << 18)
-#define CPUID_EXT_SSE41 (1U << 19)
-#define CPUID_EXT_SSE42 (1U << 20)
-#define CPUID_EXT_X2APIC (1U << 21)
-#define CPUID_EXT_MOVBE (1U << 22)
-#define CPUID_EXT_POPCNT (1U << 23)
-#define CPUID_EXT_TSC_DEADLINE_TIMER (1U << 24)
-#define CPUID_EXT_AES (1U << 25)
-#define CPUID_EXT_XSAVE (1U << 26)
-#define CPUID_EXT_OSXSAVE (1U << 27)
-#define CPUID_EXT_AVX (1U << 28)
-#define CPUID_EXT_F16C (1U << 29)
-#define CPUID_EXT_RDRAND (1U << 30)
-#define CPUID_EXT_HYPERVISOR (1U << 31)
-
-#define CPUID_EXT2_FPU (1U << 0)
-#define CPUID_EXT2_VME (1U << 1)
-#define CPUID_EXT2_DE (1U << 2)
-#define CPUID_EXT2_PSE (1U << 3)
-#define CPUID_EXT2_TSC (1U << 4)
-#define CPUID_EXT2_MSR (1U << 5)
-#define CPUID_EXT2_PAE (1U << 6)
-#define CPUID_EXT2_MCE (1U << 7)
-#define CPUID_EXT2_CX8 (1U << 8)
-#define CPUID_EXT2_APIC (1U << 9)
-#define CPUID_EXT2_SYSCALL (1U << 11)
-#define CPUID_EXT2_MTRR (1U << 12)
-#define CPUID_EXT2_PGE (1U << 13)
-#define CPUID_EXT2_MCA (1U << 14)
-#define CPUID_EXT2_CMOV (1U << 15)
-#define CPUID_EXT2_PAT (1U << 16)
-#define CPUID_EXT2_PSE36 (1U << 17)
-#define CPUID_EXT2_MP (1U << 19)
-#define CPUID_EXT2_NX (1U << 20)
-#define CPUID_EXT2_MMXEXT (1U << 22)
-#define CPUID_EXT2_MMX (1U << 23)
-#define CPUID_EXT2_FXSR (1U << 24)
-#define CPUID_EXT2_FFXSR (1U << 25)
-#define CPUID_EXT2_PDPE1GB (1U << 26)
-#define CPUID_EXT2_RDTSCP (1U << 27)
-#define CPUID_EXT2_LM (1U << 29)
-#define CPUID_EXT2_3DNOWEXT (1U << 30)
-#define CPUID_EXT2_3DNOW (1U << 31)
-
-/* CPUID[8000_0001].EDX bits that are aliase of CPUID[1].EDX bits on AMD CPUs */
-#define CPUID_EXT2_AMD_ALIASES (CPUID_EXT2_FPU | CPUID_EXT2_VME | \
- CPUID_EXT2_DE | CPUID_EXT2_PSE | \
- CPUID_EXT2_TSC | CPUID_EXT2_MSR | \
- CPUID_EXT2_PAE | CPUID_EXT2_MCE | \
- CPUID_EXT2_CX8 | CPUID_EXT2_APIC | \
- CPUID_EXT2_MTRR | CPUID_EXT2_PGE | \
- CPUID_EXT2_MCA | CPUID_EXT2_CMOV | \
- CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | \
- CPUID_EXT2_MMX | CPUID_EXT2_FXSR)
-
-#define CPUID_EXT3_LAHF_LM (1U << 0)
-#define CPUID_EXT3_CMP_LEG (1U << 1)
-#define CPUID_EXT3_SVM (1U << 2)
-#define CPUID_EXT3_EXTAPIC (1U << 3)
-#define CPUID_EXT3_CR8LEG (1U << 4)
-#define CPUID_EXT3_ABM (1U << 5)
-#define CPUID_EXT3_SSE4A (1U << 6)
-#define CPUID_EXT3_MISALIGNSSE (1U << 7)
-#define CPUID_EXT3_3DNOWPREFETCH (1U << 8)
-#define CPUID_EXT3_OSVW (1U << 9)
-#define CPUID_EXT3_IBS (1U << 10)
-#define CPUID_EXT3_XOP (1U << 11)
-#define CPUID_EXT3_SKINIT (1U << 12)
-#define CPUID_EXT3_WDT (1U << 13)
-#define CPUID_EXT3_LWP (1U << 15)
-#define CPUID_EXT3_FMA4 (1U << 16)
-#define CPUID_EXT3_TCE (1U << 17)
-#define CPUID_EXT3_NODEID (1U << 19)
-#define CPUID_EXT3_TBM (1U << 21)
-#define CPUID_EXT3_TOPOEXT (1U << 22)
-#define CPUID_EXT3_PERFCORE (1U << 23)
-#define CPUID_EXT3_PERFNB (1U << 24)
-
-#define CPUID_SVM_NPT (1U << 0)
-#define CPUID_SVM_LBRV (1U << 1)
-#define CPUID_SVM_SVMLOCK (1U << 2)
-#define CPUID_SVM_NRIPSAVE (1U << 3)
-#define CPUID_SVM_TSCSCALE (1U << 4)
-#define CPUID_SVM_VMCBCLEAN (1U << 5)
-#define CPUID_SVM_FLUSHASID (1U << 6)
-#define CPUID_SVM_DECODEASSIST (1U << 7)
-#define CPUID_SVM_PAUSEFILTER (1U << 10)
-#define CPUID_SVM_PFTHRESHOLD (1U << 12)
-
-#define CPUID_7_0_EBX_FSGSBASE (1U << 0)
-#define CPUID_7_0_EBX_BMI1 (1U << 3)
-#define CPUID_7_0_EBX_HLE (1U << 4)
-#define CPUID_7_0_EBX_AVX2 (1U << 5)
-#define CPUID_7_0_EBX_SMEP (1U << 7)
-#define CPUID_7_0_EBX_BMI2 (1U << 8)
-#define CPUID_7_0_EBX_ERMS (1U << 9)
-#define CPUID_7_0_EBX_INVPCID (1U << 10)
-#define CPUID_7_0_EBX_RTM (1U << 11)
-#define CPUID_7_0_EBX_MPX (1U << 14)
-#define CPUID_7_0_EBX_AVX512F (1U << 16) /* AVX-512 Foundation */
-#define CPUID_7_0_EBX_AVX512DQ (1U << 17) /* AVX-512 Doubleword & Quadword Instrs */
-#define CPUID_7_0_EBX_RDSEED (1U << 18)
-#define CPUID_7_0_EBX_ADX (1U << 19)
-#define CPUID_7_0_EBX_SMAP (1U << 20)
-#define CPUID_7_0_EBX_AVX512IFMA (1U << 21) /* AVX-512 Integer Fused Multiply Add */
-#define CPUID_7_0_EBX_PCOMMIT (1U << 22) /* Persistent Commit */
-#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23) /* Flush a Cache Line Optimized */
-#define CPUID_7_0_EBX_CLWB (1U << 24) /* Cache Line Write Back */
-#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */
-#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */
-#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
-#define CPUID_7_0_EBX_AVX512BW (1U << 30) /* AVX-512 Byte and Word Instructions */
-#define CPUID_7_0_EBX_AVX512VL (1U << 31) /* AVX-512 Vector Length Extensions */
-
-#define CPUID_7_0_ECX_VBMI (1U << 1) /* AVX-512 Vector Byte Manipulation Instrs */
-#define CPUID_7_0_ECX_UMIP (1U << 2)
-#define CPUID_7_0_ECX_PKU (1U << 3)
-#define CPUID_7_0_ECX_OSPKE (1U << 4)
-#define CPUID_7_0_ECX_RDPID (1U << 22)
-
-#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */
-#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */
-
-#define CPUID_XSAVE_XSAVEOPT (1U << 0)
-#define CPUID_XSAVE_XSAVEC (1U << 1)
-#define CPUID_XSAVE_XGETBV1 (1U << 2)
-#define CPUID_XSAVE_XSAVES (1U << 3)
-
-#define CPUID_6_EAX_ARAT (1U << 2)
-
-/* CPUID[0x80000007].EDX flags: */
-#define CPUID_APM_INVTSC (1U << 8)
-
-#define CPUID_VENDOR_SZ 12
-
-#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
-#define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
-#define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
-#define CPUID_VENDOR_INTEL "GenuineIntel"
-
-#define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */
-#define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */
-#define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */
-#define CPUID_VENDOR_AMD "AuthenticAMD"
-
-#define CPUID_VENDOR_VIA "CentaurHauls"
-
-#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */
-#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */
-
-/* CPUID[0xB].ECX level types */
-#define CPUID_TOPOLOGY_LEVEL_INVALID (0U << 8)
-#define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8)
-#define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8)
-
-#ifndef HYPERV_SPINLOCK_NEVER_RETRY
-#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
-#endif
-
-#define EXCP00_DIVZ 0
-#define EXCP01_DB 1
-#define EXCP02_NMI 2
-#define EXCP03_INT3 3
-#define EXCP04_INTO 4
-#define EXCP05_BOUND 5
-#define EXCP06_ILLOP 6
-#define EXCP07_PREX 7
-#define EXCP08_DBLE 8
-#define EXCP09_XERR 9
-#define EXCP0A_TSS 10
-#define EXCP0B_NOSEG 11
-#define EXCP0C_STACK 12
-#define EXCP0D_GPF 13
-#define EXCP0E_PAGE 14
-#define EXCP10_COPR 16
-#define EXCP11_ALGN 17
-#define EXCP12_MCHK 18
-
-#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
- for syscall instruction */
-
-/* i386-specific interrupt pending bits. */
-#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1
-#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
-#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
-#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
-#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
-#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_1
-#define CPU_INTERRUPT_TPR CPU_INTERRUPT_TGT_INT_2
-
-/* Use a clearer name for this. */
-#define CPU_INTERRUPT_INIT CPU_INTERRUPT_RESET
-
-/* Instead of computing the condition codes after each x86 instruction,
- * QEMU just stores one operand (called CC_SRC), the result
- * (called CC_DST) and the type of operation (called CC_OP). When the
- * condition codes are needed, the condition codes can be calculated
- * using this information. Condition codes are not generated if they
- * are only needed for conditional branches.
- */
-typedef enum {
- CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
- CC_OP_EFLAGS, /* all cc are explicitly computed, CC_SRC = flags */
-
- CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */
- CC_OP_MULW,
- CC_OP_MULL,
- CC_OP_MULQ,
-
- CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_ADDW,
- CC_OP_ADDL,
- CC_OP_ADDQ,
-
- CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_ADCW,
- CC_OP_ADCL,
- CC_OP_ADCQ,
-
- CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_SUBW,
- CC_OP_SUBL,
- CC_OP_SUBQ,
-
- CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_SBBW,
- CC_OP_SBBL,
- CC_OP_SBBQ,
-
- CC_OP_LOGICB, /* modify all flags, CC_DST = res */
- CC_OP_LOGICW,
- CC_OP_LOGICL,
- CC_OP_LOGICQ,
-
- CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
- CC_OP_INCW,
- CC_OP_INCL,
- CC_OP_INCQ,
-
- CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
- CC_OP_DECW,
- CC_OP_DECL,
- CC_OP_DECQ,
-
- CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.msb = C */
- CC_OP_SHLW,
- CC_OP_SHLL,
- CC_OP_SHLQ,
-
- CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
- CC_OP_SARW,
- CC_OP_SARL,
- CC_OP_SARQ,
-
- CC_OP_BMILGB, /* Z,S via CC_DST, C = SRC==0; O=0; P,A undefined */
- CC_OP_BMILGW,
- CC_OP_BMILGL,
- CC_OP_BMILGQ,
-
- CC_OP_ADCX, /* CC_DST = C, CC_SRC = rest. */
- CC_OP_ADOX, /* CC_DST = O, CC_SRC = rest. */
- CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */
-
- CC_OP_CLR, /* Z set, all other flags clear. */
-
- CC_OP_NB,
-} CCOp;
-
-typedef struct SegmentCache {
- uint32_t selector;
- target_ulong base;
- uint32_t limit;
- uint32_t flags;
-} SegmentCache;
-
-#define MMREG_UNION(n, bits) \
- union n { \
- uint8_t _b_##n[(bits)/8]; \
- uint16_t _w_##n[(bits)/16]; \
- uint32_t _l_##n[(bits)/32]; \
- uint64_t _q_##n[(bits)/64]; \
- float32 _s_##n[(bits)/32]; \
- float64 _d_##n[(bits)/64]; \
- }
-
-typedef MMREG_UNION(ZMMReg, 512) ZMMReg;
-typedef MMREG_UNION(MMXReg, 64) MMXReg;
-
-typedef struct BNDReg {
- uint64_t lb;
- uint64_t ub;
-} BNDReg;
-
-typedef struct BNDCSReg {
- uint64_t cfgu;
- uint64_t sts;
-} BNDCSReg;
-
-#define BNDCFG_ENABLE 1ULL
-#define BNDCFG_BNDPRESERVE 2ULL
-#define BNDCFG_BDIR_MASK TARGET_PAGE_MASK
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define ZMM_B(n) _b_ZMMReg[63 - (n)]
-#define ZMM_W(n) _w_ZMMReg[31 - (n)]
-#define ZMM_L(n) _l_ZMMReg[15 - (n)]
-#define ZMM_S(n) _s_ZMMReg[15 - (n)]
-#define ZMM_Q(n) _q_ZMMReg[7 - (n)]
-#define ZMM_D(n) _d_ZMMReg[7 - (n)]
-
-#define MMX_B(n) _b_MMXReg[7 - (n)]
-#define MMX_W(n) _w_MMXReg[3 - (n)]
-#define MMX_L(n) _l_MMXReg[1 - (n)]
-#define MMX_S(n) _s_MMXReg[1 - (n)]
-#else
-#define ZMM_B(n) _b_ZMMReg[n]
-#define ZMM_W(n) _w_ZMMReg[n]
-#define ZMM_L(n) _l_ZMMReg[n]
-#define ZMM_S(n) _s_ZMMReg[n]
-#define ZMM_Q(n) _q_ZMMReg[n]
-#define ZMM_D(n) _d_ZMMReg[n]
-
-#define MMX_B(n) _b_MMXReg[n]
-#define MMX_W(n) _w_MMXReg[n]
-#define MMX_L(n) _l_MMXReg[n]
-#define MMX_S(n) _s_MMXReg[n]
-#endif
-#define MMX_Q(n) _q_MMXReg[n]
-
-typedef union {
- floatx80 d __attribute__((aligned(16)));
- MMXReg mmx;
-} FPReg;
-
-typedef struct {
- uint64_t base;
- uint64_t mask;
-} MTRRVar;
-
-#define CPU_NB_REGS64 16
-#define CPU_NB_REGS32 8
-
-#ifdef TARGET_X86_64
-#define CPU_NB_REGS CPU_NB_REGS64
-#else
-#define CPU_NB_REGS CPU_NB_REGS32
-#endif
-
-#define MAX_FIXED_COUNTERS 3
-#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0)
-
-#define NB_MMU_MODES 3
-#define TARGET_INSN_START_EXTRA_WORDS 1
-
-#define NB_OPMASK_REGS 8
-
-/* CPU can't have 0xFFFFFFFF APIC ID, use that value to distinguish
- * that APIC ID hasn't been set yet
- */
-#define UNASSIGNED_APIC_ID 0xFFFFFFFF
-
-typedef union X86LegacyXSaveArea {
- struct {
- uint16_t fcw;
- uint16_t fsw;
- uint8_t ftw;
- uint8_t reserved;
- uint16_t fpop;
- uint64_t fpip;
- uint64_t fpdp;
- uint32_t mxcsr;
- uint32_t mxcsr_mask;
- FPReg fpregs[8];
- uint8_t xmm_regs[16][16];
- };
- uint8_t data[512];
-} X86LegacyXSaveArea;
-
-typedef struct X86XSaveHeader {
- uint64_t xstate_bv;
- uint64_t xcomp_bv;
- uint64_t reserve0;
- uint8_t reserved[40];
-} X86XSaveHeader;
-
-/* Ext. save area 2: AVX State */
-typedef struct XSaveAVX {
- uint8_t ymmh[16][16];
-} XSaveAVX;
-
-/* Ext. save area 3: BNDREG */
-typedef struct XSaveBNDREG {
- BNDReg bnd_regs[4];
-} XSaveBNDREG;
-
-/* Ext. save area 4: BNDCSR */
-typedef union XSaveBNDCSR {
- BNDCSReg bndcsr;
- uint8_t data[64];
-} XSaveBNDCSR;
-
-/* Ext. save area 5: Opmask */
-typedef struct XSaveOpmask {
- uint64_t opmask_regs[NB_OPMASK_REGS];
-} XSaveOpmask;
-
-/* Ext. save area 6: ZMM_Hi256 */
-typedef struct XSaveZMM_Hi256 {
- uint8_t zmm_hi256[16][32];
-} XSaveZMM_Hi256;
-
-/* Ext. save area 7: Hi16_ZMM */
-typedef struct XSaveHi16_ZMM {
- uint8_t hi16_zmm[16][64];
-} XSaveHi16_ZMM;
-
-/* Ext. save area 9: PKRU state */
-typedef struct XSavePKRU {
- uint32_t pkru;
- uint32_t padding;
-} XSavePKRU;
-
-typedef struct X86XSaveArea {
- X86LegacyXSaveArea legacy;
- X86XSaveHeader header;
-
- /* Extended save areas: */
-
- /* AVX State: */
- XSaveAVX avx_state;
- uint8_t padding[960 - 576 - sizeof(XSaveAVX)];
- /* MPX State: */
- XSaveBNDREG bndreg_state;
- XSaveBNDCSR bndcsr_state;
- /* AVX-512 State: */
- XSaveOpmask opmask_state;
- XSaveZMM_Hi256 zmm_hi256_state;
- XSaveHi16_ZMM hi16_zmm_state;
- /* PKRU State: */
- XSavePKRU pkru_state;
-} X86XSaveArea;
-
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240);
-QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != 0x3c0);
-QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != 0x400);
-QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != 0x440);
-QEMU_BUILD_BUG_ON(sizeof(XSaveOpmask) != 0x40);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != 0x480);
-QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != 0x680);
-QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400);
-QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != 0xA80);
-QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8);
-
-typedef enum TPRAccess {
- TPR_ACCESS_READ,
- TPR_ACCESS_WRITE,
-} TPRAccess;
-
-typedef struct CPUX86State {
- /* standard registers */
- target_ulong regs[CPU_NB_REGS];
- target_ulong eip;
- target_ulong eflags; /* eflags register. During CPU emulation, CC
- flags and DF are set to zero because they are
- stored elsewhere */
-
- /* emulator internal eflags handling */
- target_ulong cc_dst;
- target_ulong cc_src;
- target_ulong cc_src2;
- uint32_t cc_op;
- int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
- uint32_t hflags; /* TB flags, see HF_xxx constants. These flags
- are known at translation time. */
- uint32_t hflags2; /* various other flags, see HF2_xxx constants. */
-
- /* segments */
- SegmentCache segs[6]; /* selector values */
- SegmentCache ldt;
- SegmentCache tr;
- SegmentCache gdt; /* only base and limit are used */
- SegmentCache idt; /* only base and limit are used */
-
- target_ulong cr[5]; /* NOTE: cr1 is unused */
- int32_t a20_mask;
-
- BNDReg bnd_regs[4];
- BNDCSReg bndcs_regs;
- uint64_t msr_bndcfgs;
- uint64_t efer;
-
- /* Beginning of state preserved by INIT (dummy marker). */
- struct {} start_init_save;
-
- /* FPU state */
- unsigned int fpstt; /* top of stack index */
- uint16_t fpus;
- uint16_t fpuc;
- uint8_t fptags[8]; /* 0 = valid, 1 = empty */
- FPReg fpregs[8];
- /* KVM-only so far */
- uint16_t fpop;
- uint64_t fpip;
- uint64_t fpdp;
-
- /* emulator internal variables */
- float_status fp_status;
- floatx80 ft0;
-
- float_status mmx_status; /* for 3DNow! float ops */
- float_status sse_status;
- uint32_t mxcsr;
- ZMMReg xmm_regs[CPU_NB_REGS == 8 ? 8 : 32];
- ZMMReg xmm_t0;
- MMXReg mmx_t0;
-
- uint64_t opmask_regs[NB_OPMASK_REGS];
-
- /* sysenter registers */
- uint32_t sysenter_cs;
- target_ulong sysenter_esp;
- target_ulong sysenter_eip;
- uint64_t star;
-
- uint64_t vm_hsave;
-
-#ifdef TARGET_X86_64
- target_ulong lstar;
- target_ulong cstar;
- target_ulong fmask;
- target_ulong kernelgsbase;
-#endif
-
- uint64_t tsc;
- uint64_t tsc_adjust;
- uint64_t tsc_deadline;
- uint64_t tsc_aux;
-
- uint64_t xcr0;
-
- uint64_t mcg_status;
- uint64_t msr_ia32_misc_enable;
- uint64_t msr_ia32_feature_control;
-
- uint64_t msr_fixed_ctr_ctrl;
- uint64_t msr_global_ctrl;
- uint64_t msr_global_status;
- uint64_t msr_global_ovf_ctrl;
- uint64_t msr_fixed_counters[MAX_FIXED_COUNTERS];
- uint64_t msr_gp_counters[MAX_GP_COUNTERS];
- uint64_t msr_gp_evtsel[MAX_GP_COUNTERS];
-
- uint64_t pat;
- uint32_t smbase;
-
- uint32_t pkru;
-
- /* End of state preserved by INIT (dummy marker). */
- struct {} end_init_save;
-
- uint64_t system_time_msr;
- uint64_t wall_clock_msr;
- uint64_t steal_time_msr;
- uint64_t async_pf_en_msr;
- uint64_t pv_eoi_en_msr;
-
- uint64_t msr_hv_hypercall;
- uint64_t msr_hv_guest_os_id;
- uint64_t msr_hv_vapic;
- uint64_t msr_hv_tsc;
- uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
- uint64_t msr_hv_runtime;
- uint64_t msr_hv_synic_control;
- uint64_t msr_hv_synic_version;
- uint64_t msr_hv_synic_evt_page;
- uint64_t msr_hv_synic_msg_page;
- uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
- uint64_t msr_hv_stimer_config[HV_SYNIC_STIMER_COUNT];
- uint64_t msr_hv_stimer_count[HV_SYNIC_STIMER_COUNT];
-
- /* exception/interrupt handling */
- int error_code;
- int exception_is_int;
- target_ulong exception_next_eip;
- target_ulong dr[8]; /* debug registers; note dr4 and dr5 are unused */
- union {
- struct CPUBreakpoint *cpu_breakpoint[4];
- struct CPUWatchpoint *cpu_watchpoint[4];
- }; /* break/watchpoints for dr[0..3] */
- int old_exception; /* exception in flight */
-
- uint64_t vm_vmcb;
- uint64_t tsc_offset;
- uint64_t intercept;
- uint16_t intercept_cr_read;
- uint16_t intercept_cr_write;
- uint16_t intercept_dr_read;
- uint16_t intercept_dr_write;
- uint32_t intercept_exceptions;
- uint8_t v_tpr;
-
- /* KVM states, automatically cleared on reset */
- uint8_t nmi_injected;
- uint8_t nmi_pending;
-
- CPU_COMMON
-
- /* Fields from here on are preserved across CPU reset. */
- struct {} end_reset_fields;
-
- /* processor features (e.g. for CPUID insn) */
- /* Minimum level/xlevel/xlevel2, based on CPU model + features */
- uint32_t cpuid_min_level, cpuid_min_xlevel, cpuid_min_xlevel2;
- /* Maximum level/xlevel/xlevel2 value for auto-assignment: */
- uint32_t cpuid_max_level, cpuid_max_xlevel, cpuid_max_xlevel2;
- /* Actual level/xlevel/xlevel2 value: */
- uint32_t cpuid_level, cpuid_xlevel, cpuid_xlevel2;
- uint32_t cpuid_vendor1;
- uint32_t cpuid_vendor2;
- uint32_t cpuid_vendor3;
- uint32_t cpuid_version;
- FeatureWordArray features;
- uint32_t cpuid_model[12];
-
- /* MTRRs */
- uint64_t mtrr_fixed[11];
- uint64_t mtrr_deftype;
- MTRRVar mtrr_var[MSR_MTRRcap_VCNT];
-
- /* For KVM */
- uint32_t mp_state;
- int32_t exception_injected;
- int32_t interrupt_injected;
- uint8_t soft_interrupt;
- uint8_t has_error_code;
- uint32_t sipi_vector;
- bool tsc_valid;
- int64_t tsc_khz;
- int64_t user_tsc_khz; /* for sanity check only */
- void *kvm_xsave_buf;
-
- uint64_t mcg_cap;
- uint64_t mcg_ctl;
- uint64_t mcg_ext_ctl;
- uint64_t mce_banks[MCE_BANKS_DEF*4];
- uint64_t xstate_bv;
-
- /* vmstate */
- uint16_t fpus_vmstate;
- uint16_t fptag_vmstate;
- uint16_t fpregs_format_vmstate;
-
- uint64_t xss;
-
- TPRAccess tpr_access_type;
-} CPUX86State;
-
-struct kvm_msrs;
-
-/**
- * X86CPU:
- * @env: #CPUX86State
- * @migratable: If set, only migratable flags will be accepted when "enforce"
- * mode is used, and only migratable flags will be included in the "host"
- * CPU model.
- *
- * An x86 CPU.
- */
-struct X86CPU {
- /*< private >*/
- CPUState parent_obj;
- /*< public >*/
-
- CPUX86State env;
-
- bool hyperv_vapic;
- bool hyperv_relaxed_timing;
- int hyperv_spinlock_attempts;
- char *hyperv_vendor_id;
- bool hyperv_time;
- bool hyperv_crash;
- bool hyperv_reset;
- bool hyperv_vpindex;
- bool hyperv_runtime;
- bool hyperv_synic;
- bool hyperv_stimer;
- bool check_cpuid;
- bool enforce_cpuid;
- bool expose_kvm;
- bool migratable;
- bool host_features;
- uint32_t apic_id;
-
- /* if true the CPUID code directly forward host cache leaves to the guest */
- bool cache_info_passthrough;
-
- /* Features that were filtered out because of missing host capabilities */
- uint32_t filtered_features[FEATURE_WORDS];
-
- /* Enable PMU CPUID bits. This can't be enabled by default yet because
- * it doesn't have ABI stability guarantees, as it passes all PMU CPUID
- * bits returned by GET_SUPPORTED_CPUID (that depend on host CPU and kernel
- * capabilities) directly to the guest.
- */
- bool enable_pmu;
-
- /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
- * disabled by default to avoid breaking migration between QEMU with
- * different LMCE configurations.
- */
- bool enable_lmce;
-
- /* Compatibility bits for old machine types.
- * If true present virtual l3 cache for VM, the vcpus in the same virtual
- * socket share an virtual l3 cache.
- */
- bool enable_l3_cache;
-
- /* Compatibility bits for old machine types: */
- bool enable_cpuid_0xb;
-
- /* Enable auto level-increase for all CPUID leaves */
- bool full_cpuid_auto_level;
-
- /* if true fill the top bits of the MTRR_PHYSMASKn variable range */
- bool fill_mtrr_mask;
-
- /* if true override the phys_bits value with a value read from the host */
- bool host_phys_bits;
-
- /* Number of physical address bits supported */
- uint32_t phys_bits;
-
- /* in order to simplify APIC support, we leave this pointer to the
- user */
- struct DeviceState *apic_state;
- struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram;
- Notifier machine_done;
-
- struct kvm_msrs *kvm_msr_buf;
-
- int32_t socket_id;
- int32_t core_id;
- int32_t thread_id;
-};
-
-static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
-{
- return container_of(env, X86CPU, env);
-}
-
-#define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
-
-#define ENV_OFFSET offsetof(X86CPU, env)
-
-#ifndef CONFIG_USER_ONLY
-extern struct VMStateDescription vmstate_x86_cpu;
-#endif
-
-/**
- * x86_cpu_do_interrupt:
- * @cpu: vCPU the interrupt is to be handled by.
- */
-void x86_cpu_do_interrupt(CPUState *cpu);
-bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
-
-int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
-int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
-int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
-int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
-
-void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
- Error **errp);
-
-void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
- int flags);
-
-hwaddr x86_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-
-int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
-int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-
-void x86_cpu_exec_enter(CPUState *cpu);
-void x86_cpu_exec_exit(CPUState *cpu);
-
-X86CPU *cpu_x86_init(const char *cpu_model);
-void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-int cpu_x86_support_mca_broadcast(CPUX86State *env);
-
-int cpu_get_pic_interrupt(CPUX86State *s);
-/* MSDOS compatibility mode FPU exception support */
-void cpu_set_ferr(CPUX86State *s);
-
-/* this function must always be used to load data in the segment
- cache: it synchronizes the hflags with the segment cache values */
-static inline void cpu_x86_load_seg_cache(CPUX86State *env,
- int seg_reg, unsigned int selector,
- target_ulong base,
- unsigned int limit,
- unsigned int flags)
-{
- SegmentCache *sc;
- unsigned int new_hflags;
-
- sc = &env->segs[seg_reg];
- sc->selector = selector;
- sc->base = base;
- sc->limit = limit;
- sc->flags = flags;
-
- /* update the hidden flags */
- {
- if (seg_reg == R_CS) {
-#ifdef TARGET_X86_64
- if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) {
- /* long mode */
- env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
- env->hflags &= ~(HF_ADDSEG_MASK);
- } else
-#endif
- {
- /* legacy / compatibility case */
- new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
- >> (DESC_B_SHIFT - HF_CS32_SHIFT);
- env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) |
- new_hflags;
- }
- }
- if (seg_reg == R_SS) {
- int cpl = (flags >> DESC_DPL_SHIFT) & 3;
-#if HF_CPL_MASK != 3
-#error HF_CPL_MASK is hardcoded
-#endif
- env->hflags = (env->hflags & ~HF_CPL_MASK) | cpl;
- }
- new_hflags = (env->segs[R_SS].flags & DESC_B_MASK)
- >> (DESC_B_SHIFT - HF_SS32_SHIFT);
- if (env->hflags & HF_CS64_MASK) {
- /* zero base assumed for DS, ES and SS in long mode */
- } else if (!(env->cr[0] & CR0_PE_MASK) ||
- (env->eflags & VM_MASK) ||
- !(env->hflags & HF_CS32_MASK)) {
- /* XXX: try to avoid this test. The problem comes from the
- fact that is real mode or vm86 mode we only modify the
- 'base' and 'selector' fields of the segment cache to go
- faster. A solution may be to force addseg to one in
- translate-i386.c. */
- new_hflags |= HF_ADDSEG_MASK;
- } else {
- new_hflags |= ((env->segs[R_DS].base |
- env->segs[R_ES].base |
- env->segs[R_SS].base) != 0) <<
- HF_ADDSEG_SHIFT;
- }
- env->hflags = (env->hflags &
- ~(HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags;
- }
-}
-
-static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
- uint8_t sipi_vector)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
-
- env->eip = 0;
- cpu_x86_load_seg_cache(env, R_CS, sipi_vector << 8,
- sipi_vector << 12,
- env->segs[R_CS].limit,
- env->segs[R_CS].flags);
- cs->halted = 0;
-}
-
-int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
- target_ulong *base, unsigned int *limit,
- unsigned int *flags);
-
-/* op_helper.c */
-/* used for debug or cpu save/restore */
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f);
-floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper);
-
-/* cpu-exec.c */
-/* the following helpers are only usable in user mode simulation as
- they can trigger unexpected exceptions */
-void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
-void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32);
-void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32);
-
-/* you can call this signal handler from your SIGBUS and SIGSEGV
- signal handlers to inform the virtual CPU of exceptions. non zero
- is returned if the signal was handled by the virtual CPU. */
-int cpu_x86_signal_handler(int host_signum, void *pinfo,
- void *puc);
-
-/* cpu.c */
-void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx);
-void cpu_clear_apic_feature(CPUX86State *env);
-void host_cpuid(uint32_t function, uint32_t count,
- uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
-
-/* helper.c */
-int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr,
- int is_write, int mmu_idx);
-void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
-
-#ifndef CONFIG_USER_ONLY
-uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr);
-uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr);
-uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr);
-uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr);
-void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val);
-void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val);
-void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val);
-void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val);
-void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val);
-#endif
-
-void breakpoint_handler(CPUState *cs);
-
-/* will be suppressed */
-void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
-void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
-void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
-void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7);
-
-/* hw/pc.c */
-uint64_t cpu_get_tsc(CPUX86State *env);
-
-#define TARGET_PAGE_BITS 12
-
-#ifdef TARGET_X86_64
-#define TARGET_PHYS_ADDR_SPACE_BITS 52
-/* ??? This is really 48 bits, sign-extended, but the only thing
- accessible to userland with bit 48 set is the VSYSCALL, and that
- is handled via other mechanisms. */
-#define TARGET_VIRT_ADDR_SPACE_BITS 47
-#else
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#endif
-
-/* XXX: This value should match the one returned by CPUID
- * and in exec.c */
-# if defined(TARGET_X86_64)
-# define TCG_PHYS_ADDR_BITS 40
-# else
-# define TCG_PHYS_ADDR_BITS 36
-# endif
-
-#define PHYS_ADDR_MASK MAKE_64BIT_MASK(0, TCG_PHYS_ADDR_BITS)
-
-#define cpu_init(cpu_model) CPU(cpu_x86_init(cpu_model))
-
-#define cpu_signal_handler cpu_x86_signal_handler
-#define cpu_list x86_cpu_list
-
-/* MMU modes definitions */
-#define MMU_MODE0_SUFFIX _ksmap
-#define MMU_MODE1_SUFFIX _user
-#define MMU_MODE2_SUFFIX _knosmap /* SMAP disabled or CPL<3 && AC=1 */
-#define MMU_KSMAP_IDX 0
-#define MMU_USER_IDX 1
-#define MMU_KNOSMAP_IDX 2
-static inline int cpu_mmu_index(CPUX86State *env, bool ifetch)
-{
- return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
- (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
- ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
-}
-
-static inline int cpu_mmu_index_kernel(CPUX86State *env)
-{
- return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
- ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK))
- ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
-}
-
-#define CC_DST (env->cc_dst)
-#define CC_SRC (env->cc_src)
-#define CC_SRC2 (env->cc_src2)
-#define CC_OP (env->cc_op)
-
-/* n must be a constant to be efficient */
-static inline target_long lshift(target_long x, int n)
-{
- if (n >= 0) {
- return x << n;
- } else {
- return x >> (-n);
- }
-}
-
-/* float macros */
-#define FT0 (env->ft0)
-#define ST0 (env->fpregs[env->fpstt].d)
-#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
-#define ST1 ST(1)
-
-/* translate.c */
-void tcg_x86_init(void);
-
-#include "exec/cpu-all.h"
-#include "svm.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "hw/i386/apic.h"
-#endif
-
-static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
- target_ulong *cs_base, uint32_t *flags)
-{
- *cs_base = env->segs[R_CS].base;
- *pc = *cs_base + env->eip;
- *flags = env->hflags |
- (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK));
-}
-
-void do_cpu_init(X86CPU *cpu);
-void do_cpu_sipi(X86CPU *cpu);
-
-#define MCE_INJECT_BROADCAST 1
-#define MCE_INJECT_UNCOND_AO 2
-
-void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
- uint64_t status, uint64_t mcg_status, uint64_t addr,
- uint64_t misc, int flags);
-
-/* excp_helper.c */
-void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index);
-void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index,
- uintptr_t retaddr);
-void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index,
- int error_code);
-void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index,
- int error_code, uintptr_t retaddr);
-void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int,
- int error_code, int next_eip_addend);
-
-/* cc_helper.c */
-extern const uint8_t parity_table[256];
-uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
-void update_fp_status(CPUX86State *env);
-
-static inline uint32_t cpu_compute_eflags(CPUX86State *env)
-{
- return env->eflags | cpu_cc_compute_all(env, CC_OP) | (env->df & DF_MASK);
-}
-
-/* NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
- * after generating a call to a helper that uses this.
- */
-static inline void cpu_load_eflags(CPUX86State *env, int eflags,
- int update_mask)
-{
- CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
- CC_OP = CC_OP_EFLAGS;
- env->df = 1 - (2 * ((eflags >> 10) & 1));
- env->eflags = (env->eflags & ~update_mask) |
- (eflags & update_mask) | 0x2;
-}
-
-/* load efer and update the corresponding hflags. XXX: do consistency
- checks with cpuid bits? */
-static inline void cpu_load_efer(CPUX86State *env, uint64_t val)
-{
- env->efer = val;
- env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
- if (env->efer & MSR_EFER_LMA) {
- env->hflags |= HF_LMA_MASK;
- }
- if (env->efer & MSR_EFER_SVME) {
- env->hflags |= HF_SVME_MASK;
- }
-}
-
-static inline MemTxAttrs cpu_get_mem_attrs(CPUX86State *env)
-{
- return ((MemTxAttrs) { .secure = (env->hflags & HF_SMM_MASK) != 0 });
-}
-
-/* fpu_helper.c */
-void cpu_set_mxcsr(CPUX86State *env, uint32_t val);
-void cpu_set_fpuc(CPUX86State *env, uint16_t val);
-
-/* mem_helper.c */
-void helper_lock_init(void);
-
-/* svm_helper.c */
-void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
- uint64_t param);
-void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);
-
-/* seg_helper.c */
-void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
-
-/* smm_helper.c */
-void do_smm_enter(X86CPU *cpu);
-void cpu_smm_update(X86CPU *cpu);
-
-/* apic.c */
-void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
-void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
- TPRAccess access);
-
-
-/* Change the value of a KVM-specific default
- *
- * If value is NULL, no default will be set and the original
- * value from the CPU model table will be kept.
- *
- * It is valid to call this function only for properties that
- * are already present in the kvm_default_props table.
- */
-void x86_cpu_change_kvm_default(const char *prop, const char *value);
-
-/* mpx_helper.c */
-void cpu_sync_bndcs_hflags(CPUX86State *env);
-
-/* Return name of 32-bit register, from a R_* constant */
-const char *get_register_name_32(unsigned int reg);
-
-void enable_compat_apic_id_mode(void);
-
-#define APIC_DEFAULT_ADDRESS 0xfee00000
-#define APIC_SPACE_SIZE 0x100000
-
-void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
- fprintf_function cpu_fprintf, int flags);
-
-/* cpu.c */
-bool cpu_is_bsp(X86CPU *cpu);
-
-#endif /* I386_CPU_H */
diff --git a/target-i386/excp_helper.c b/target-i386/excp_helper.c
deleted file mode 100644
index f0dc4996c1..0000000000
--- a/target-i386/excp_helper.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * x86 exception helpers
- *
- * 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 "cpu.h"
-#include "exec/exec-all.h"
-#include "qemu/log.h"
-#include "sysemu/sysemu.h"
-#include "exec/helper-proto.h"
-
-void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend)
-{
- raise_interrupt(env, intno, 1, 0, next_eip_addend);
-}
-
-void helper_raise_exception(CPUX86State *env, int exception_index)
-{
- raise_exception(env, exception_index);
-}
-
-/*
- * Check nested exceptions and change to double or triple fault if
- * needed. It should only be called, if this is not an interrupt.
- * Returns the new exception number.
- */
-static int check_exception(CPUX86State *env, int intno, int *error_code)
-{
- int first_contributory = env->old_exception == 0 ||
- (env->old_exception >= 10 &&
- env->old_exception <= 13);
- int second_contributory = intno == 0 ||
- (intno >= 10 && intno <= 13);
-
- qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
- env->old_exception, intno);
-
-#if !defined(CONFIG_USER_ONLY)
- if (env->old_exception == EXCP08_DBLE) {
- if (env->hflags & HF_SVMI_MASK) {
- cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */
- }
-
- qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
-
- qemu_system_reset_request();
- return EXCP_HLT;
- }
-#endif
-
- if ((first_contributory && second_contributory)
- || (env->old_exception == EXCP0E_PAGE &&
- (second_contributory || (intno == EXCP0E_PAGE)))) {
- intno = EXCP08_DBLE;
- *error_code = 0;
- }
-
- if (second_contributory || (intno == EXCP0E_PAGE) ||
- (intno == EXCP08_DBLE)) {
- env->old_exception = intno;
- }
-
- return intno;
-}
-
-/*
- * Signal an interruption. It is executed in the main CPU loop.
- * is_int is TRUE if coming from the int instruction. next_eip is the
- * env->eip value AFTER the interrupt instruction. It is only relevant if
- * is_int is TRUE.
- */
-static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno,
- int is_int, int error_code,
- int next_eip_addend,
- uintptr_t retaddr)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
-
- if (!is_int) {
- cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
- error_code);
- intno = check_exception(env, intno, &error_code);
- } else {
- cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0);
- }
-
- cs->exception_index = intno;
- env->error_code = error_code;
- env->exception_is_int = is_int;
- env->exception_next_eip = env->eip + next_eip_addend;
- cpu_loop_exit_restore(cs, retaddr);
-}
-
-/* shortcuts to generate exceptions */
-
-void QEMU_NORETURN raise_interrupt(CPUX86State *env, int intno, int is_int,
- int error_code, int next_eip_addend)
-{
- raise_interrupt2(env, intno, is_int, error_code, next_eip_addend, 0);
-}
-
-void raise_exception_err(CPUX86State *env, int exception_index,
- int error_code)
-{
- raise_interrupt2(env, exception_index, 0, error_code, 0, 0);
-}
-
-void raise_exception_err_ra(CPUX86State *env, int exception_index,
- int error_code, uintptr_t retaddr)
-{
- raise_interrupt2(env, exception_index, 0, error_code, 0, retaddr);
-}
-
-void raise_exception(CPUX86State *env, int exception_index)
-{
- raise_interrupt2(env, exception_index, 0, 0, 0, 0);
-}
-
-void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr)
-{
- raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
-}
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
deleted file mode 100644
index 2049a8c01d..0000000000
--- a/target-i386/fpu_helper.c
+++ /dev/null
@@ -1,1625 +0,0 @@
-/*
- * x86 FPU, MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI helpers
- *
- * 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 <math.h>
-#include "cpu.h"
-#include "exec/helper-proto.h"
-#include "qemu/host-utils.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
-
-#define FPU_RC_MASK 0xc00
-#define FPU_RC_NEAR 0x000
-#define FPU_RC_DOWN 0x400
-#define FPU_RC_UP 0x800
-#define FPU_RC_CHOP 0xc00
-
-#define MAXTAN 9223372036854775808.0
-
-/* the following deal with x86 long double-precision numbers */
-#define MAXEXPD 0x7fff
-#define EXPBIAS 16383
-#define EXPD(fp) (fp.l.upper & 0x7fff)
-#define SIGND(fp) ((fp.l.upper) & 0x8000)
-#define MANTD(fp) (fp.l.lower)
-#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
-
-#define FPUS_IE (1 << 0)
-#define FPUS_DE (1 << 1)
-#define FPUS_ZE (1 << 2)
-#define FPUS_OE (1 << 3)
-#define FPUS_UE (1 << 4)
-#define FPUS_PE (1 << 5)
-#define FPUS_SF (1 << 6)
-#define FPUS_SE (1 << 7)
-#define FPUS_B (1 << 15)
-
-#define FPUC_EM 0x3f
-
-#define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL)
-#define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
-#define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
-
-static inline void fpush(CPUX86State *env)
-{
- env->fpstt = (env->fpstt - 1) & 7;
- env->fptags[env->fpstt] = 0; /* validate stack entry */
-}
-
-static inline void fpop(CPUX86State *env)
-{
- env->fptags[env->fpstt] = 1; /* invalidate stack entry */
- env->fpstt = (env->fpstt + 1) & 7;
-}
-
-static inline floatx80 helper_fldt(CPUX86State *env, target_ulong ptr,
- uintptr_t retaddr)
-{
- CPU_LDoubleU temp;
-
- temp.l.lower = cpu_ldq_data_ra(env, ptr, retaddr);
- temp.l.upper = cpu_lduw_data_ra(env, ptr + 8, retaddr);
- return temp.d;
-}
-
-static inline void helper_fstt(CPUX86State *env, floatx80 f, target_ulong ptr,
- uintptr_t retaddr)
-{
- CPU_LDoubleU temp;
-
- temp.d = f;
- cpu_stq_data_ra(env, ptr, temp.l.lower, retaddr);
- cpu_stw_data_ra(env, ptr + 8, temp.l.upper, retaddr);
-}
-
-/* x87 FPU helpers */
-
-static inline double floatx80_to_double(CPUX86State *env, floatx80 a)
-{
- union {
- float64 f64;
- double d;
- } u;
-
- u.f64 = floatx80_to_float64(a, &env->fp_status);
- return u.d;
-}
-
-static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
-{
- union {
- float64 f64;
- double d;
- } u;
-
- u.d = a;
- return float64_to_floatx80(u.f64, &env->fp_status);
-}
-
-static void fpu_set_exception(CPUX86State *env, int mask)
-{
- env->fpus |= mask;
- if (env->fpus & (~env->fpuc & FPUC_EM)) {
- env->fpus |= FPUS_SE | FPUS_B;
- }
-}
-
-static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b)
-{
- if (floatx80_is_zero(b)) {
- fpu_set_exception(env, FPUS_ZE);
- }
- return floatx80_div(a, b, &env->fp_status);
-}
-
-static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr)
-{
- if (env->cr[0] & CR0_NE_MASK) {
- raise_exception_ra(env, EXCP10_COPR, retaddr);
- }
-#if !defined(CONFIG_USER_ONLY)
- else {
- cpu_set_ferr(env);
- }
-#endif
-}
-
-void helper_flds_FT0(CPUX86State *env, uint32_t val)
-{
- union {
- float32 f;
- uint32_t i;
- } u;
-
- u.i = val;
- FT0 = float32_to_floatx80(u.f, &env->fp_status);
-}
-
-void helper_fldl_FT0(CPUX86State *env, uint64_t val)
-{
- union {
- float64 f;
- uint64_t i;
- } u;
-
- u.i = val;
- FT0 = float64_to_floatx80(u.f, &env->fp_status);
-}
-
-void helper_fildl_FT0(CPUX86State *env, int32_t val)
-{
- FT0 = int32_to_floatx80(val, &env->fp_status);
-}
-
-void helper_flds_ST0(CPUX86State *env, uint32_t val)
-{
- int new_fpstt;
- union {
- float32 f;
- uint32_t i;
- } u;
-
- new_fpstt = (env->fpstt - 1) & 7;
- u.i = val;
- env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
- env->fpstt = new_fpstt;
- env->fptags[new_fpstt] = 0; /* validate stack entry */
-}
-
-void helper_fldl_ST0(CPUX86State *env, uint64_t val)
-{
- int new_fpstt;
- union {
- float64 f;
- uint64_t i;
- } u;
-
- new_fpstt = (env->fpstt - 1) & 7;
- u.i = val;
- env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
- env->fpstt = new_fpstt;
- env->fptags[new_fpstt] = 0; /* validate stack entry */
-}
-
-void helper_fildl_ST0(CPUX86State *env, int32_t val)
-{
- int new_fpstt;
-
- new_fpstt = (env->fpstt - 1) & 7;
- env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
- env->fpstt = new_fpstt;
- env->fptags[new_fpstt] = 0; /* validate stack entry */
-}
-
-void helper_fildll_ST0(CPUX86State *env, int64_t val)
-{
- int new_fpstt;
-
- new_fpstt = (env->fpstt - 1) & 7;
- env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
- env->fpstt = new_fpstt;
- env->fptags[new_fpstt] = 0; /* validate stack entry */
-}
-
-uint32_t helper_fsts_ST0(CPUX86State *env)
-{
- union {
- float32 f;
- uint32_t i;
- } u;
-
- u.f = floatx80_to_float32(ST0, &env->fp_status);
- return u.i;
-}
-
-uint64_t helper_fstl_ST0(CPUX86State *env)
-{
- union {
- float64 f;
- uint64_t i;
- } u;
-
- u.f = floatx80_to_float64(ST0, &env->fp_status);
- return u.i;
-}
-
-int32_t helper_fist_ST0(CPUX86State *env)
-{
- int32_t val;
-
- val = floatx80_to_int32(ST0, &env->fp_status);
- if (val != (int16_t)val) {
- val = -32768;
- }
- return val;
-}
-
-int32_t helper_fistl_ST0(CPUX86State *env)
-{
- int32_t val;
- signed char old_exp_flags;
-
- old_exp_flags = get_float_exception_flags(&env->fp_status);
- set_float_exception_flags(0, &env->fp_status);
-
- val = floatx80_to_int32(ST0, &env->fp_status);
- if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
- val = 0x80000000;
- }
- set_float_exception_flags(get_float_exception_flags(&env->fp_status)
- | old_exp_flags, &env->fp_status);
- return val;
-}
-
-int64_t helper_fistll_ST0(CPUX86State *env)
-{
- int64_t val;
- signed char old_exp_flags;
-
- old_exp_flags = get_float_exception_flags(&env->fp_status);
- set_float_exception_flags(0, &env->fp_status);
-
- val = floatx80_to_int64(ST0, &env->fp_status);
- if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
- val = 0x8000000000000000ULL;
- }
- set_float_exception_flags(get_float_exception_flags(&env->fp_status)
- | old_exp_flags, &env->fp_status);
- return val;
-}
-
-int32_t helper_fistt_ST0(CPUX86State *env)
-{
- int32_t val;
-
- val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
- if (val != (int16_t)val) {
- val = -32768;
- }
- return val;
-}
-
-int32_t helper_fisttl_ST0(CPUX86State *env)
-{
- return floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
-}
-
-int64_t helper_fisttll_ST0(CPUX86State *env)
-{
- return floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
-}
-
-void helper_fldt_ST0(CPUX86State *env, target_ulong ptr)
-{
- int new_fpstt;
-
- new_fpstt = (env->fpstt - 1) & 7;
- env->fpregs[new_fpstt].d = helper_fldt(env, ptr, GETPC());
- env->fpstt = new_fpstt;
- env->fptags[new_fpstt] = 0; /* validate stack entry */
-}
-
-void helper_fstt_ST0(CPUX86State *env, target_ulong ptr)
-{
- helper_fstt(env, ST0, ptr, GETPC());
-}
-
-void helper_fpush(CPUX86State *env)
-{
- fpush(env);
-}
-
-void helper_fpop(CPUX86State *env)
-{
- fpop(env);
-}
-
-void helper_fdecstp(CPUX86State *env)
-{
- env->fpstt = (env->fpstt - 1) & 7;
- env->fpus &= ~0x4700;
-}
-
-void helper_fincstp(CPUX86State *env)
-{
- env->fpstt = (env->fpstt + 1) & 7;
- env->fpus &= ~0x4700;
-}
-
-/* FPU move */
-
-void helper_ffree_STN(CPUX86State *env, int st_index)
-{
- env->fptags[(env->fpstt + st_index) & 7] = 1;
-}
-
-void helper_fmov_ST0_FT0(CPUX86State *env)
-{
- ST0 = FT0;
-}
-
-void helper_fmov_FT0_STN(CPUX86State *env, int st_index)
-{
- FT0 = ST(st_index);
-}
-
-void helper_fmov_ST0_STN(CPUX86State *env, int st_index)
-{
- ST0 = ST(st_index);
-}
-
-void helper_fmov_STN_ST0(CPUX86State *env, int st_index)
-{
- ST(st_index) = ST0;
-}
-
-void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
-{
- floatx80 tmp;
-
- tmp = ST(st_index);
- ST(st_index) = ST0;
- ST0 = tmp;
-}
-
-/* FPU operations */
-
-static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
-
-void helper_fcom_ST0_FT0(CPUX86State *env)
-{
- int ret;
-
- ret = floatx80_compare(ST0, FT0, &env->fp_status);
- env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
-}
-
-void helper_fucom_ST0_FT0(CPUX86State *env)
-{
- int ret;
-
- ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
- env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
-}
-
-static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
-
-void helper_fcomi_ST0_FT0(CPUX86State *env)
-{
- int eflags;
- int ret;
-
- ret = floatx80_compare(ST0, FT0, &env->fp_status);
- eflags = cpu_cc_compute_all(env, CC_OP);
- eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
- CC_SRC = eflags;
-}
-
-void helper_fucomi_ST0_FT0(CPUX86State *env)
-{
- int eflags;
- int ret;
-
- ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
- eflags = cpu_cc_compute_all(env, CC_OP);
- eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
- CC_SRC = eflags;
-}
-
-void helper_fadd_ST0_FT0(CPUX86State *env)
-{
- ST0 = floatx80_add(ST0, FT0, &env->fp_status);
-}
-
-void helper_fmul_ST0_FT0(CPUX86State *env)
-{
- ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
-}
-
-void helper_fsub_ST0_FT0(CPUX86State *env)
-{
- ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
-}
-
-void helper_fsubr_ST0_FT0(CPUX86State *env)
-{
- ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
-}
-
-void helper_fdiv_ST0_FT0(CPUX86State *env)
-{
- ST0 = helper_fdiv(env, ST0, FT0);
-}
-
-void helper_fdivr_ST0_FT0(CPUX86State *env)
-{
- ST0 = helper_fdiv(env, FT0, ST0);
-}
-
-/* fp operations between STN and ST0 */
-
-void helper_fadd_STN_ST0(CPUX86State *env, int st_index)
-{
- ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
-}
-
-void helper_fmul_STN_ST0(CPUX86State *env, int st_index)
-{
- ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
-}
-
-void helper_fsub_STN_ST0(CPUX86State *env, int st_index)
-{
- ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
-}
-
-void helper_fsubr_STN_ST0(CPUX86State *env, int st_index)
-{
- ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status);
-}
-
-void helper_fdiv_STN_ST0(CPUX86State *env, int st_index)
-{
- floatx80 *p;
-
- p = &ST(st_index);
- *p = helper_fdiv(env, *p, ST0);
-}
-
-void helper_fdivr_STN_ST0(CPUX86State *env, int st_index)
-{
- floatx80 *p;
-
- p = &ST(st_index);
- *p = helper_fdiv(env, ST0, *p);
-}
-
-/* misc FPU operations */
-void helper_fchs_ST0(CPUX86State *env)
-{
- ST0 = floatx80_chs(ST0);
-}
-
-void helper_fabs_ST0(CPUX86State *env)
-{
- ST0 = floatx80_abs(ST0);
-}
-
-void helper_fld1_ST0(CPUX86State *env)
-{
- ST0 = floatx80_one;
-}
-
-void helper_fldl2t_ST0(CPUX86State *env)
-{
- ST0 = floatx80_l2t;
-}
-
-void helper_fldl2e_ST0(CPUX86State *env)
-{
- ST0 = floatx80_l2e;
-}
-
-void helper_fldpi_ST0(CPUX86State *env)
-{
- ST0 = floatx80_pi;
-}
-
-void helper_fldlg2_ST0(CPUX86State *env)
-{
- ST0 = floatx80_lg2;
-}
-
-void helper_fldln2_ST0(CPUX86State *env)
-{
- ST0 = floatx80_ln2;
-}
-
-void helper_fldz_ST0(CPUX86State *env)
-{
- ST0 = floatx80_zero;
-}
-
-void helper_fldz_FT0(CPUX86State *env)
-{
- FT0 = floatx80_zero;
-}
-
-uint32_t helper_fnstsw(CPUX86State *env)
-{
- return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
-}
-
-uint32_t helper_fnstcw(CPUX86State *env)
-{
- return env->fpuc;
-}
-
-void update_fp_status(CPUX86State *env)
-{
- int rnd_type;
-
- /* set rounding mode */
- switch (env->fpuc & FPU_RC_MASK) {
- default:
- case FPU_RC_NEAR:
- rnd_type = float_round_nearest_even;
- break;
- case FPU_RC_DOWN:
- rnd_type = float_round_down;
- break;
- case FPU_RC_UP:
- rnd_type = float_round_up;
- break;
- case FPU_RC_CHOP:
- rnd_type = float_round_to_zero;
- break;
- }
- set_float_rounding_mode(rnd_type, &env->fp_status);
- switch ((env->fpuc >> 8) & 3) {
- case 0:
- rnd_type = 32;
- break;
- case 2:
- rnd_type = 64;
- break;
- case 3:
- default:
- rnd_type = 80;
- break;
- }
- set_floatx80_rounding_precision(rnd_type, &env->fp_status);
-}
-
-void helper_fldcw(CPUX86State *env, uint32_t val)
-{
- cpu_set_fpuc(env, val);
-}
-
-void helper_fclex(CPUX86State *env)
-{
- env->fpus &= 0x7f00;
-}
-
-void helper_fwait(CPUX86State *env)
-{
- if (env->fpus & FPUS_SE) {
- fpu_raise_exception(env, GETPC());
- }
-}
-
-void helper_fninit(CPUX86State *env)
-{
- env->fpus = 0;
- env->fpstt = 0;
- cpu_set_fpuc(env, 0x37f);
- env->fptags[0] = 1;
- env->fptags[1] = 1;
- env->fptags[2] = 1;
- env->fptags[3] = 1;
- env->fptags[4] = 1;
- env->fptags[5] = 1;
- env->fptags[6] = 1;
- env->fptags[7] = 1;
-}
-
-/* BCD ops */
-
-void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
-{
- floatx80 tmp;
- uint64_t val;
- unsigned int v;
- int i;
-
- val = 0;
- for (i = 8; i >= 0; i--) {
- v = cpu_ldub_data_ra(env, ptr + i, GETPC());
- val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
- }
- tmp = int64_to_floatx80(val, &env->fp_status);
- if (cpu_ldub_data_ra(env, ptr + 9, GETPC()) & 0x80) {
- tmp = floatx80_chs(tmp);
- }
- fpush(env);
- ST0 = tmp;
-}
-
-void helper_fbst_ST0(CPUX86State *env, target_ulong ptr)
-{
- int v;
- target_ulong mem_ref, mem_end;
- int64_t val;
-
- val = floatx80_to_int64(ST0, &env->fp_status);
- mem_ref = ptr;
- mem_end = mem_ref + 9;
- if (val < 0) {
- cpu_stb_data_ra(env, mem_end, 0x80, GETPC());
- val = -val;
- } else {
- cpu_stb_data_ra(env, mem_end, 0x00, GETPC());
- }
- while (mem_ref < mem_end) {
- if (val == 0) {
- break;
- }
- v = val % 100;
- val = val / 100;
- v = ((v / 10) << 4) | (v % 10);
- cpu_stb_data_ra(env, mem_ref++, v, GETPC());
- }
- while (mem_ref < mem_end) {
- cpu_stb_data_ra(env, mem_ref++, 0, GETPC());
- }
-}
-
-void helper_f2xm1(CPUX86State *env)
-{
- double val = floatx80_to_double(env, ST0);
-
- val = pow(2.0, val) - 1.0;
- ST0 = double_to_floatx80(env, val);
-}
-
-void helper_fyl2x(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if (fptemp > 0.0) {
- fptemp = log(fptemp) / log(2.0); /* log2(ST) */
- fptemp *= floatx80_to_double(env, ST1);
- ST1 = double_to_floatx80(env, fptemp);
- fpop(env);
- } else {
- env->fpus &= ~0x4700;
- env->fpus |= 0x400;
- }
-}
-
-void helper_fptan(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
- env->fpus |= 0x400;
- } else {
- fptemp = tan(fptemp);
- ST0 = double_to_floatx80(env, fptemp);
- fpush(env);
- ST0 = floatx80_one;
- env->fpus &= ~0x400; /* C2 <-- 0 */
- /* the above code is for |arg| < 2**52 only */
- }
-}
-
-void helper_fpatan(CPUX86State *env)
-{
- double fptemp, fpsrcop;
-
- fpsrcop = floatx80_to_double(env, ST1);
- fptemp = floatx80_to_double(env, ST0);
- ST1 = double_to_floatx80(env, atan2(fpsrcop, fptemp));
- fpop(env);
-}
-
-void helper_fxtract(CPUX86State *env)
-{
- CPU_LDoubleU temp;
-
- temp.d = ST0;
-
- if (floatx80_is_zero(ST0)) {
- /* Easy way to generate -inf and raising division by 0 exception */
- ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero,
- &env->fp_status);
- fpush(env);
- ST0 = temp.d;
- } else {
- int expdif;
-
- expdif = EXPD(temp) - EXPBIAS;
- /* DP exponent bias */
- ST0 = int32_to_floatx80(expdif, &env->fp_status);
- fpush(env);
- BIASEXPONENT(temp);
- ST0 = temp.d;
- }
-}
-
-void helper_fprem1(CPUX86State *env)
-{
- double st0, st1, dblq, fpsrcop, fptemp;
- CPU_LDoubleU fpsrcop1, fptemp1;
- int expdif;
- signed long long int q;
-
- st0 = floatx80_to_double(env, ST0);
- st1 = floatx80_to_double(env, ST1);
-
- if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
- ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- return;
- }
-
- fpsrcop = st0;
- fptemp = st1;
- fpsrcop1.d = ST0;
- fptemp1.d = ST1;
- expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
-
- if (expdif < 0) {
- /* optimisation? taken from the AMD docs */
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- /* ST0 is unchanged */
- return;
- }
-
- if (expdif < 53) {
- dblq = fpsrcop / fptemp;
- /* round dblq towards nearest integer */
- dblq = rint(dblq);
- st0 = fpsrcop - fptemp * dblq;
-
- /* convert dblq to q by truncating towards zero */
- if (dblq < 0.0) {
- q = (signed long long int)(-dblq);
- } else {
- q = (signed long long int)dblq;
- }
-
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- /* (C0,C3,C1) <-- (q2,q1,q0) */
- env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
- env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
- env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
- } else {
- env->fpus |= 0x400; /* C2 <-- 1 */
- fptemp = pow(2.0, expdif - 50);
- fpsrcop = (st0 / st1) / fptemp;
- /* fpsrcop = integer obtained by chopping */
- fpsrcop = (fpsrcop < 0.0) ?
- -(floor(fabs(fpsrcop))) : floor(fpsrcop);
- st0 -= (st1 * fpsrcop * fptemp);
- }
- ST0 = double_to_floatx80(env, st0);
-}
-
-void helper_fprem(CPUX86State *env)
-{
- double st0, st1, dblq, fpsrcop, fptemp;
- CPU_LDoubleU fpsrcop1, fptemp1;
- int expdif;
- signed long long int q;
-
- st0 = floatx80_to_double(env, ST0);
- st1 = floatx80_to_double(env, ST1);
-
- if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
- ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- return;
- }
-
- fpsrcop = st0;
- fptemp = st1;
- fpsrcop1.d = ST0;
- fptemp1.d = ST1;
- expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
-
- if (expdif < 0) {
- /* optimisation? taken from the AMD docs */
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- /* ST0 is unchanged */
- return;
- }
-
- if (expdif < 53) {
- dblq = fpsrcop / fptemp; /* ST0 / ST1 */
- /* round dblq towards zero */
- dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
- st0 = fpsrcop - fptemp * dblq; /* fpsrcop is ST0 */
-
- /* convert dblq to q by truncating towards zero */
- if (dblq < 0.0) {
- q = (signed long long int)(-dblq);
- } else {
- q = (signed long long int)dblq;
- }
-
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- /* (C0,C3,C1) <-- (q2,q1,q0) */
- env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
- env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
- env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
- } else {
- int N = 32 + (expdif % 32); /* as per AMD docs */
-
- env->fpus |= 0x400; /* C2 <-- 1 */
- fptemp = pow(2.0, (double)(expdif - N));
- fpsrcop = (st0 / st1) / fptemp;
- /* fpsrcop = integer obtained by chopping */
- fpsrcop = (fpsrcop < 0.0) ?
- -(floor(fabs(fpsrcop))) : floor(fpsrcop);
- st0 -= (st1 * fpsrcop * fptemp);
- }
- ST0 = double_to_floatx80(env, st0);
-}
-
-void helper_fyl2xp1(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if ((fptemp + 1.0) > 0.0) {
- fptemp = log(fptemp + 1.0) / log(2.0); /* log2(ST + 1.0) */
- fptemp *= floatx80_to_double(env, ST1);
- ST1 = double_to_floatx80(env, fptemp);
- fpop(env);
- } else {
- env->fpus &= ~0x4700;
- env->fpus |= 0x400;
- }
-}
-
-void helper_fsqrt(CPUX86State *env)
-{
- if (floatx80_is_neg(ST0)) {
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- env->fpus |= 0x400;
- }
- ST0 = floatx80_sqrt(ST0, &env->fp_status);
-}
-
-void helper_fsincos(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
- env->fpus |= 0x400;
- } else {
- ST0 = double_to_floatx80(env, sin(fptemp));
- fpush(env);
- ST0 = double_to_floatx80(env, cos(fptemp));
- env->fpus &= ~0x400; /* C2 <-- 0 */
- /* the above code is for |arg| < 2**63 only */
- }
-}
-
-void helper_frndint(CPUX86State *env)
-{
- ST0 = floatx80_round_to_int(ST0, &env->fp_status);
-}
-
-void helper_fscale(CPUX86State *env)
-{
- if (floatx80_is_any_nan(ST1)) {
- ST0 = ST1;
- } else {
- int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
- ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
- }
-}
-
-void helper_fsin(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
- env->fpus |= 0x400;
- } else {
- ST0 = double_to_floatx80(env, sin(fptemp));
- env->fpus &= ~0x400; /* C2 <-- 0 */
- /* the above code is for |arg| < 2**53 only */
- }
-}
-
-void helper_fcos(CPUX86State *env)
-{
- double fptemp = floatx80_to_double(env, ST0);
-
- if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
- env->fpus |= 0x400;
- } else {
- ST0 = double_to_floatx80(env, cos(fptemp));
- env->fpus &= ~0x400; /* C2 <-- 0 */
- /* the above code is for |arg| < 2**63 only */
- }
-}
-
-void helper_fxam_ST0(CPUX86State *env)
-{
- CPU_LDoubleU temp;
- int expdif;
-
- temp.d = ST0;
-
- env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
- if (SIGND(temp)) {
- env->fpus |= 0x200; /* C1 <-- 1 */
- }
-
- /* XXX: test fptags too */
- expdif = EXPD(temp);
- if (expdif == MAXEXPD) {
- if (MANTD(temp) == 0x8000000000000000ULL) {
- env->fpus |= 0x500; /* Infinity */
- } else {
- env->fpus |= 0x100; /* NaN */
- }
- } else if (expdif == 0) {
- if (MANTD(temp) == 0) {
- env->fpus |= 0x4000; /* Zero */
- } else {
- env->fpus |= 0x4400; /* Denormal */
- }
- } else {
- env->fpus |= 0x400;
- }
-}
-
-static void do_fstenv(CPUX86State *env, target_ulong ptr, int data32,
- uintptr_t retaddr)
-{
- int fpus, fptag, exp, i;
- uint64_t mant;
- CPU_LDoubleU tmp;
-
- fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- fptag = 0;
- for (i = 7; i >= 0; i--) {
- fptag <<= 2;
- if (env->fptags[i]) {
- fptag |= 3;
- } else {
- tmp.d = env->fpregs[i].d;
- exp = EXPD(tmp);
- mant = MANTD(tmp);
- if (exp == 0 && mant == 0) {
- /* zero */
- fptag |= 1;
- } else if (exp == 0 || exp == MAXEXPD
- || (mant & (1LL << 63)) == 0) {
- /* NaNs, infinity, denormal */
- fptag |= 2;
- }
- }
- }
- if (data32) {
- /* 32 bit */
- cpu_stl_data_ra(env, ptr, env->fpuc, retaddr);
- cpu_stl_data_ra(env, ptr + 4, fpus, retaddr);
- cpu_stl_data_ra(env, ptr + 8, fptag, retaddr);
- cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */
- cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */
- cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */
- cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */
- } else {
- /* 16 bit */
- cpu_stw_data_ra(env, ptr, env->fpuc, retaddr);
- cpu_stw_data_ra(env, ptr + 2, fpus, retaddr);
- cpu_stw_data_ra(env, ptr + 4, fptag, retaddr);
- cpu_stw_data_ra(env, ptr + 6, 0, retaddr);
- cpu_stw_data_ra(env, ptr + 8, 0, retaddr);
- cpu_stw_data_ra(env, ptr + 10, 0, retaddr);
- cpu_stw_data_ra(env, ptr + 12, 0, retaddr);
- }
-}
-
-void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
-{
- do_fstenv(env, ptr, data32, GETPC());
-}
-
-static void do_fldenv(CPUX86State *env, target_ulong ptr, int data32,
- uintptr_t retaddr)
-{
- int i, fpus, fptag;
-
- if (data32) {
- cpu_set_fpuc(env, cpu_lduw_data_ra(env, ptr, retaddr));
- fpus = cpu_lduw_data_ra(env, ptr + 4, retaddr);
- fptag = cpu_lduw_data_ra(env, ptr + 8, retaddr);
- } else {
- cpu_set_fpuc(env, cpu_lduw_data_ra(env, ptr, retaddr));
- fpus = cpu_lduw_data_ra(env, ptr + 2, retaddr);
- fptag = cpu_lduw_data_ra(env, ptr + 4, retaddr);
- }
- env->fpstt = (fpus >> 11) & 7;
- env->fpus = fpus & ~0x3800;
- for (i = 0; i < 8; i++) {
- env->fptags[i] = ((fptag & 3) == 3);
- fptag >>= 2;
- }
-}
-
-void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
-{
- do_fldenv(env, ptr, data32, GETPC());
-}
-
-void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
-{
- floatx80 tmp;
- int i;
-
- do_fstenv(env, ptr, data32, GETPC());
-
- ptr += (14 << data32);
- for (i = 0; i < 8; i++) {
- tmp = ST(i);
- helper_fstt(env, tmp, ptr, GETPC());
- ptr += 10;
- }
-
- /* fninit */
- env->fpus = 0;
- env->fpstt = 0;
- cpu_set_fpuc(env, 0x37f);
- env->fptags[0] = 1;
- env->fptags[1] = 1;
- env->fptags[2] = 1;
- env->fptags[3] = 1;
- env->fptags[4] = 1;
- env->fptags[5] = 1;
- env->fptags[6] = 1;
- env->fptags[7] = 1;
-}
-
-void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
-{
- floatx80 tmp;
- int i;
-
- do_fldenv(env, ptr, data32, GETPC());
- ptr += (14 << data32);
-
- for (i = 0; i < 8; i++) {
- tmp = helper_fldt(env, ptr, GETPC());
- ST(i) = tmp;
- ptr += 10;
- }
-}
-
-#if defined(CONFIG_USER_ONLY)
-void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32)
-{
- helper_fsave(env, ptr, data32);
-}
-
-void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32)
-{
- helper_frstor(env, ptr, data32);
-}
-#endif
-
-#define XO(X) offsetof(X86XSaveArea, X)
-
-static void do_xsave_fpu(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- int fpus, fptag, i;
- target_ulong addr;
-
- fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- fptag = 0;
- for (i = 0; i < 8; i++) {
- fptag |= (env->fptags[i] << i);
- }
-
- cpu_stw_data_ra(env, ptr + XO(legacy.fcw), env->fpuc, ra);
- cpu_stw_data_ra(env, ptr + XO(legacy.fsw), fpus, ra);
- cpu_stw_data_ra(env, ptr + XO(legacy.ftw), fptag ^ 0xff, ra);
-
- /* In 32-bit mode this is eip, sel, dp, sel.
- In 64-bit mode this is rip, rdp.
- But in either case we don't write actual data, just zeros. */
- cpu_stq_data_ra(env, ptr + XO(legacy.fpip), 0, ra); /* eip+sel; rip */
- cpu_stq_data_ra(env, ptr + XO(legacy.fpdp), 0, ra); /* edp+sel; rdp */
-
- addr = ptr + XO(legacy.fpregs);
- for (i = 0; i < 8; i++) {
- floatx80 tmp = ST(i);
- helper_fstt(env, tmp, addr, ra);
- addr += 16;
- }
-}
-
-static void do_xsave_mxcsr(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- cpu_stl_data_ra(env, ptr + XO(legacy.mxcsr), env->mxcsr, ra);
- cpu_stl_data_ra(env, ptr + XO(legacy.mxcsr_mask), 0x0000ffff, ra);
-}
-
-static void do_xsave_sse(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- int i, nb_xmm_regs;
- target_ulong addr;
-
- if (env->hflags & HF_CS64_MASK) {
- nb_xmm_regs = 16;
- } else {
- nb_xmm_regs = 8;
- }
-
- addr = ptr + XO(legacy.xmm_regs);
- for (i = 0; i < nb_xmm_regs; i++) {
- cpu_stq_data_ra(env, addr, env->xmm_regs[i].ZMM_Q(0), ra);
- cpu_stq_data_ra(env, addr + 8, env->xmm_regs[i].ZMM_Q(1), ra);
- addr += 16;
- }
-}
-
-static void do_xsave_bndregs(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
- int i;
-
- for (i = 0; i < 4; i++, addr += 16) {
- cpu_stq_data_ra(env, addr, env->bnd_regs[i].lb, ra);
- cpu_stq_data_ra(env, addr + 8, env->bnd_regs[i].ub, ra);
- }
-}
-
-static void do_xsave_bndcsr(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- cpu_stq_data_ra(env, ptr + offsetof(XSaveBNDCSR, bndcsr.cfgu),
- env->bndcs_regs.cfgu, ra);
- cpu_stq_data_ra(env, ptr + offsetof(XSaveBNDCSR, bndcsr.sts),
- env->bndcs_regs.sts, ra);
-}
-
-static void do_xsave_pkru(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- cpu_stq_data_ra(env, ptr, env->pkru, ra);
-}
-
-void helper_fxsave(CPUX86State *env, target_ulong ptr)
-{
- uintptr_t ra = GETPC();
-
- /* The operand must be 16 byte aligned */
- if (ptr & 0xf) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- do_xsave_fpu(env, ptr, ra);
-
- if (env->cr[4] & CR4_OSFXSR_MASK) {
- do_xsave_mxcsr(env, ptr, ra);
- /* Fast FXSAVE leaves out the XMM registers */
- if (!(env->efer & MSR_EFER_FFXSR)
- || (env->hflags & HF_CPL_MASK)
- || !(env->hflags & HF_LMA_MASK)) {
- do_xsave_sse(env, ptr, ra);
- }
- }
-}
-
-static uint64_t get_xinuse(CPUX86State *env)
-{
- uint64_t inuse = -1;
-
- /* For the most part, we don't track XINUSE. We could calculate it
- here for all components, but it's probably less work to simply
- indicate in use. That said, the state of BNDREGS is important
- enough to track in HFLAGS, so we might as well use that here. */
- if ((env->hflags & HF_MPX_IU_MASK) == 0) {
- inuse &= ~XSTATE_BNDREGS_MASK;
- }
- return inuse;
-}
-
-static void do_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm,
- uint64_t inuse, uint64_t opt, uintptr_t ra)
-{
- uint64_t old_bv, new_bv;
-
- /* The OS must have enabled XSAVE. */
- if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
- raise_exception_ra(env, EXCP06_ILLOP, ra);
- }
-
- /* The operand must be 64 byte aligned. */
- if (ptr & 63) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- /* Never save anything not enabled by XCR0. */
- rfbm &= env->xcr0;
- opt &= rfbm;
-
- if (opt & XSTATE_FP_MASK) {
- do_xsave_fpu(env, ptr, ra);
- }
- if (rfbm & XSTATE_SSE_MASK) {
- /* Note that saving MXCSR is not suppressed by XSAVEOPT. */
- do_xsave_mxcsr(env, ptr, ra);
- }
- if (opt & XSTATE_SSE_MASK) {
- do_xsave_sse(env, ptr, ra);
- }
- if (opt & XSTATE_BNDREGS_MASK) {
- do_xsave_bndregs(env, ptr + XO(bndreg_state), ra);
- }
- if (opt & XSTATE_BNDCSR_MASK) {
- do_xsave_bndcsr(env, ptr + XO(bndcsr_state), ra);
- }
- if (opt & XSTATE_PKRU_MASK) {
- do_xsave_pkru(env, ptr + XO(pkru_state), ra);
- }
-
- /* Update the XSTATE_BV field. */
- old_bv = cpu_ldq_data_ra(env, ptr + XO(header.xstate_bv), ra);
- new_bv = (old_bv & ~rfbm) | (inuse & rfbm);
- cpu_stq_data_ra(env, ptr + XO(header.xstate_bv), new_bv, ra);
-}
-
-void helper_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
-{
- do_xsave(env, ptr, rfbm, get_xinuse(env), -1, GETPC());
-}
-
-void helper_xsaveopt(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
-{
- uint64_t inuse = get_xinuse(env);
- do_xsave(env, ptr, rfbm, inuse, inuse, GETPC());
-}
-
-static void do_xrstor_fpu(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- int i, fpuc, fpus, fptag;
- target_ulong addr;
-
- fpuc = cpu_lduw_data_ra(env, ptr + XO(legacy.fcw), ra);
- fpus = cpu_lduw_data_ra(env, ptr + XO(legacy.fsw), ra);
- fptag = cpu_lduw_data_ra(env, ptr + XO(legacy.ftw), ra);
- cpu_set_fpuc(env, fpuc);
- env->fpstt = (fpus >> 11) & 7;
- env->fpus = fpus & ~0x3800;
- fptag ^= 0xff;
- for (i = 0; i < 8; i++) {
- env->fptags[i] = ((fptag >> i) & 1);
- }
-
- addr = ptr + XO(legacy.fpregs);
- for (i = 0; i < 8; i++) {
- floatx80 tmp = helper_fldt(env, addr, ra);
- ST(i) = tmp;
- addr += 16;
- }
-}
-
-static void do_xrstor_mxcsr(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- cpu_set_mxcsr(env, cpu_ldl_data_ra(env, ptr + XO(legacy.mxcsr), ra));
-}
-
-static void do_xrstor_sse(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- int i, nb_xmm_regs;
- target_ulong addr;
-
- if (env->hflags & HF_CS64_MASK) {
- nb_xmm_regs = 16;
- } else {
- nb_xmm_regs = 8;
- }
-
- addr = ptr + XO(legacy.xmm_regs);
- for (i = 0; i < nb_xmm_regs; i++) {
- env->xmm_regs[i].ZMM_Q(0) = cpu_ldq_data_ra(env, addr, ra);
- env->xmm_regs[i].ZMM_Q(1) = cpu_ldq_data_ra(env, addr + 8, ra);
- addr += 16;
- }
-}
-
-static void do_xrstor_bndregs(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
- int i;
-
- for (i = 0; i < 4; i++, addr += 16) {
- env->bnd_regs[i].lb = cpu_ldq_data_ra(env, addr, ra);
- env->bnd_regs[i].ub = cpu_ldq_data_ra(env, addr + 8, ra);
- }
-}
-
-static void do_xrstor_bndcsr(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- /* FIXME: Extend highest implemented bit of linear address. */
- env->bndcs_regs.cfgu
- = cpu_ldq_data_ra(env, ptr + offsetof(XSaveBNDCSR, bndcsr.cfgu), ra);
- env->bndcs_regs.sts
- = cpu_ldq_data_ra(env, ptr + offsetof(XSaveBNDCSR, bndcsr.sts), ra);
-}
-
-static void do_xrstor_pkru(CPUX86State *env, target_ulong ptr, uintptr_t ra)
-{
- env->pkru = cpu_ldq_data_ra(env, ptr, ra);
-}
-
-void helper_fxrstor(CPUX86State *env, target_ulong ptr)
-{
- uintptr_t ra = GETPC();
-
- /* The operand must be 16 byte aligned */
- if (ptr & 0xf) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- do_xrstor_fpu(env, ptr, ra);
-
- if (env->cr[4] & CR4_OSFXSR_MASK) {
- do_xrstor_mxcsr(env, ptr, ra);
- /* Fast FXRSTOR leaves out the XMM registers */
- if (!(env->efer & MSR_EFER_FFXSR)
- || (env->hflags & HF_CPL_MASK)
- || !(env->hflags & HF_LMA_MASK)) {
- do_xrstor_sse(env, ptr, ra);
- }
- }
-}
-
-void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
-{
- uintptr_t ra = GETPC();
- uint64_t xstate_bv, xcomp_bv, reserve0;
-
- rfbm &= env->xcr0;
-
- /* The OS must have enabled XSAVE. */
- if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
- raise_exception_ra(env, EXCP06_ILLOP, ra);
- }
-
- /* The operand must be 64 byte aligned. */
- if (ptr & 63) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- xstate_bv = cpu_ldq_data_ra(env, ptr + XO(header.xstate_bv), ra);
-
- if ((int64_t)xstate_bv < 0) {
- /* FIXME: Compact form. */
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- /* Standard form. */
-
- /* The XSTATE_BV field must not set bits not present in XCR0. */
- if (xstate_bv & ~env->xcr0) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- /* The XCOMP_BV field must be zero. Note that, as of the April 2016
- revision, the description of the XSAVE Header (Vol 1, Sec 13.4.2)
- describes only XCOMP_BV, but the description of the standard form
- of XRSTOR (Vol 1, Sec 13.8.1) checks bytes 23:8 for zero, which
- includes the next 64-bit field. */
- xcomp_bv = cpu_ldq_data_ra(env, ptr + XO(header.xcomp_bv), ra);
- reserve0 = cpu_ldq_data_ra(env, ptr + XO(header.reserve0), ra);
- if (xcomp_bv || reserve0) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- }
-
- if (rfbm & XSTATE_FP_MASK) {
- if (xstate_bv & XSTATE_FP_MASK) {
- do_xrstor_fpu(env, ptr, ra);
- } else {
- helper_fninit(env);
- memset(env->fpregs, 0, sizeof(env->fpregs));
- }
- }
- if (rfbm & XSTATE_SSE_MASK) {
- /* Note that the standard form of XRSTOR loads MXCSR from memory
- whether or not the XSTATE_BV bit is set. */
- do_xrstor_mxcsr(env, ptr, ra);
- if (xstate_bv & XSTATE_SSE_MASK) {
- do_xrstor_sse(env, ptr, ra);
- } else {
- /* ??? When AVX is implemented, we may have to be more
- selective in the clearing. */
- memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
- }
- }
- if (rfbm & XSTATE_BNDREGS_MASK) {
- if (xstate_bv & XSTATE_BNDREGS_MASK) {
- do_xrstor_bndregs(env, ptr + XO(bndreg_state), ra);
- env->hflags |= HF_MPX_IU_MASK;
- } else {
- memset(env->bnd_regs, 0, sizeof(env->bnd_regs));
- env->hflags &= ~HF_MPX_IU_MASK;
- }
- }
- if (rfbm & XSTATE_BNDCSR_MASK) {
- if (xstate_bv & XSTATE_BNDCSR_MASK) {
- do_xrstor_bndcsr(env, ptr + XO(bndcsr_state), ra);
- } else {
- memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs));
- }
- cpu_sync_bndcs_hflags(env);
- }
- if (rfbm & XSTATE_PKRU_MASK) {
- uint64_t old_pkru = env->pkru;
- if (xstate_bv & XSTATE_PKRU_MASK) {
- do_xrstor_pkru(env, ptr + XO(pkru_state), ra);
- } else {
- env->pkru = 0;
- }
- if (env->pkru != old_pkru) {
- CPUState *cs = CPU(x86_env_get_cpu(env));
- tlb_flush(cs, 1);
- }
- }
-}
-
-#undef XO
-
-uint64_t helper_xgetbv(CPUX86State *env, uint32_t ecx)
-{
- /* The OS must have enabled XSAVE. */
- if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
- raise_exception_ra(env, EXCP06_ILLOP, GETPC());
- }
-
- switch (ecx) {
- case 0:
- return env->xcr0;
- case 1:
- if (env->features[FEAT_XSAVE] & CPUID_XSAVE_XGETBV1) {
- return env->xcr0 & get_xinuse(env);
- }
- break;
- }
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
-}
-
-void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
-{
- uint32_t dummy, ena_lo, ena_hi;
- uint64_t ena;
-
- /* The OS must have enabled XSAVE. */
- if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
- raise_exception_ra(env, EXCP06_ILLOP, GETPC());
- }
-
- /* Only XCR0 is defined at present; the FPU may not be disabled. */
- if (ecx != 0 || (mask & XSTATE_FP_MASK) == 0) {
- goto do_gpf;
- }
-
- /* Disallow enabling unimplemented features. */
- cpu_x86_cpuid(env, 0x0d, 0, &ena_lo, &dummy, &dummy, &ena_hi);
- ena = ((uint64_t)ena_hi << 32) | ena_lo;
- if (mask & ~ena) {
- goto do_gpf;
- }
-
- /* Disallow enabling only half of MPX. */
- if ((mask ^ (mask * (XSTATE_BNDCSR_MASK / XSTATE_BNDREGS_MASK)))
- & XSTATE_BNDCSR_MASK) {
- goto do_gpf;
- }
-
- env->xcr0 = mask;
- cpu_sync_bndcs_hflags(env);
- return;
-
- do_gpf:
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
-}
-
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
-{
- CPU_LDoubleU temp;
-
- temp.d = f;
- *pmant = temp.l.lower;
- *pexp = temp.l.upper;
-}
-
-floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
-{
- CPU_LDoubleU temp;
-
- temp.l.upper = upper;
- temp.l.lower = mant;
- return temp.d;
-}
-
-/* MMX/SSE */
-/* XXX: optimize by storing fptt and fptags in the static cpu state */
-
-#define SSE_DAZ 0x0040
-#define SSE_RC_MASK 0x6000
-#define SSE_RC_NEAR 0x0000
-#define SSE_RC_DOWN 0x2000
-#define SSE_RC_UP 0x4000
-#define SSE_RC_CHOP 0x6000
-#define SSE_FZ 0x8000
-
-void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr)
-{
- int rnd_type;
-
- env->mxcsr = mxcsr;
-
- /* set rounding mode */
- switch (mxcsr & SSE_RC_MASK) {
- default:
- case SSE_RC_NEAR:
- rnd_type = float_round_nearest_even;
- break;
- case SSE_RC_DOWN:
- rnd_type = float_round_down;
- break;
- case SSE_RC_UP:
- rnd_type = float_round_up;
- break;
- case SSE_RC_CHOP:
- rnd_type = float_round_to_zero;
- break;
- }
- set_float_rounding_mode(rnd_type, &env->sse_status);
-
- /* set denormals are zero */
- set_flush_inputs_to_zero((mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
-
- /* set flush to zero */
- set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
-}
-
-void cpu_set_fpuc(CPUX86State *env, uint16_t val)
-{
- env->fpuc = val;
- update_fp_status(env);
-}
-
-void helper_ldmxcsr(CPUX86State *env, uint32_t val)
-{
- cpu_set_mxcsr(env, val);
-}
-
-void helper_enter_mmx(CPUX86State *env)
-{
- env->fpstt = 0;
- *(uint32_t *)(env->fptags) = 0;
- *(uint32_t *)(env->fptags + 4) = 0;
-}
-
-void helper_emms(CPUX86State *env)
-{
- /* set to empty state */
- *(uint32_t *)(env->fptags) = 0x01010101;
- *(uint32_t *)(env->fptags + 4) = 0x01010101;
-}
-
-/* XXX: suppress */
-void helper_movq(CPUX86State *env, void *d, void *s)
-{
- *(uint64_t *)d = *(uint64_t *)s;
-}
-
-#define SHIFT 0
-#include "ops_sse.h"
-
-#define SHIFT 1
-#include "ops_sse.h"
diff --git a/target-i386/gdbstub.c b/target-i386/gdbstub.c
deleted file mode 100644
index c494535df1..0000000000
--- a/target-i386/gdbstub.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * x86 gdb server stub
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- * Copyright (c) 2013 SUSE LINUX Products GmbH
- *
- * 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-common.h"
-#include "cpu.h"
-#include "exec/gdbstub.h"
-
-#ifdef TARGET_X86_64
-static const int gpr_map[16] = {
- R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
- 8, 9, 10, 11, 12, 13, 14, 15
-};
-#else
-#define gpr_map gpr_map32
-#endif
-static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
-
-#define IDX_IP_REG CPU_NB_REGS
-#define IDX_FLAGS_REG (IDX_IP_REG + 1)
-#define IDX_SEG_REGS (IDX_FLAGS_REG + 1)
-#define IDX_FP_REGS (IDX_SEG_REGS + 6)
-#define IDX_XMM_REGS (IDX_FP_REGS + 16)
-#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS)
-
-int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- if (n < CPU_NB_REGS) {
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- return gdb_get_reg64(mem_buf, env->regs[gpr_map[n]]);
- } else if (n < CPU_NB_REGS32) {
- return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
- }
- } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
-#else
- memset(mem_buf, 0, 10);
-#endif
- return 10;
- } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
- n -= IDX_XMM_REGS;
- if (n < CPU_NB_REGS32 ||
- (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
- stq_p(mem_buf, env->xmm_regs[n].ZMM_Q(0));
- stq_p(mem_buf + 8, env->xmm_regs[n].ZMM_Q(1));
- return 16;
- }
- } else {
- switch (n) {
- case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- return gdb_get_reg64(mem_buf, env->eip);
- } else {
- return gdb_get_reg32(mem_buf, env->eip);
- }
- case IDX_FLAGS_REG:
- return gdb_get_reg32(mem_buf, env->eflags);
-
- case IDX_SEG_REGS:
- return gdb_get_reg32(mem_buf, env->segs[R_CS].selector);
- case IDX_SEG_REGS + 1:
- return gdb_get_reg32(mem_buf, env->segs[R_SS].selector);
- case IDX_SEG_REGS + 2:
- return gdb_get_reg32(mem_buf, env->segs[R_DS].selector);
- case IDX_SEG_REGS + 3:
- return gdb_get_reg32(mem_buf, env->segs[R_ES].selector);
- case IDX_SEG_REGS + 4:
- return gdb_get_reg32(mem_buf, env->segs[R_FS].selector);
- case IDX_SEG_REGS + 5:
- return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
-
- case IDX_FP_REGS + 8:
- return gdb_get_reg32(mem_buf, env->fpuc);
- case IDX_FP_REGS + 9:
- return gdb_get_reg32(mem_buf, (env->fpus & ~0x3800) |
- (env->fpstt & 0x7) << 11);
- case IDX_FP_REGS + 10:
- return gdb_get_reg32(mem_buf, 0); /* ftag */
- case IDX_FP_REGS + 11:
- return gdb_get_reg32(mem_buf, 0); /* fiseg */
- case IDX_FP_REGS + 12:
- return gdb_get_reg32(mem_buf, 0); /* fioff */
- case IDX_FP_REGS + 13:
- return gdb_get_reg32(mem_buf, 0); /* foseg */
- case IDX_FP_REGS + 14:
- return gdb_get_reg32(mem_buf, 0); /* fooff */
- case IDX_FP_REGS + 15:
- return gdb_get_reg32(mem_buf, 0); /* fop */
-
- case IDX_MXCSR_REG:
- return gdb_get_reg32(mem_buf, env->mxcsr);
- }
- }
- return 0;
-}
-
-static int x86_cpu_gdb_load_seg(X86CPU *cpu, int sreg, uint8_t *mem_buf)
-{
- CPUX86State *env = &cpu->env;
- uint16_t selector = ldl_p(mem_buf);
-
- if (selector != env->segs[sreg].selector) {
-#if defined(CONFIG_USER_ONLY)
- cpu_x86_load_seg(env, sreg, selector);
-#else
- unsigned int limit, flags;
- target_ulong base;
-
- if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
- int dpl = (env->eflags & VM_MASK) ? 3 : 0;
- base = selector << 4;
- limit = 0xffff;
- flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK | (dpl << DESC_DPL_SHIFT);
- } else {
- if (!cpu_x86_get_descr_debug(env, selector, &base, &limit,
- &flags)) {
- return 4;
- }
- }
- cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
-#endif
- }
- return 4;
-}
-
-int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- uint32_t tmp;
-
- if (n < CPU_NB_REGS) {
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- env->regs[gpr_map[n]] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- } else if (n < CPU_NB_REGS32) {
- n = gpr_map32[n];
- env->regs[n] &= ~0xffffffffUL;
- env->regs[n] |= (uint32_t)ldl_p(mem_buf);
- return 4;
- }
- } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
-#endif
- return 10;
- } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
- n -= IDX_XMM_REGS;
- if (n < CPU_NB_REGS32 ||
- (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
- env->xmm_regs[n].ZMM_Q(0) = ldq_p(mem_buf);
- env->xmm_regs[n].ZMM_Q(1) = ldq_p(mem_buf + 8);
- return 16;
- }
- } else {
- switch (n) {
- case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- env->eip = ldq_p(mem_buf);
- return 8;
- } else {
- env->eip &= ~0xffffffffUL;
- env->eip |= (uint32_t)ldl_p(mem_buf);
- return 4;
- }
- case IDX_FLAGS_REG:
- env->eflags = ldl_p(mem_buf);
- return 4;
-
- case IDX_SEG_REGS:
- return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);
- case IDX_SEG_REGS + 1:
- return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);
- case IDX_SEG_REGS + 2:
- return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);
- case IDX_SEG_REGS + 3:
- return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);
- case IDX_SEG_REGS + 4:
- return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);
- case IDX_SEG_REGS + 5:
- return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
-
- case IDX_FP_REGS + 8:
- cpu_set_fpuc(env, ldl_p(mem_buf));
- return 4;
- case IDX_FP_REGS + 9:
- tmp = ldl_p(mem_buf);
- env->fpstt = (tmp >> 11) & 7;
- env->fpus = tmp & ~0x3800;
- return 4;
- case IDX_FP_REGS + 10: /* ftag */
- return 4;
- case IDX_FP_REGS + 11: /* fiseg */
- return 4;
- case IDX_FP_REGS + 12: /* fioff */
- return 4;
- case IDX_FP_REGS + 13: /* foseg */
- return 4;
- case IDX_FP_REGS + 14: /* fooff */
- return 4;
- case IDX_FP_REGS + 15: /* fop */
- return 4;
-
- case IDX_MXCSR_REG:
- cpu_set_mxcsr(env, ldl_p(mem_buf));
- return 4;
- }
- }
- /* Unrecognised register. */
- return 0;
-}
diff --git a/target-i386/helper.c b/target-i386/helper.c
deleted file mode 100644
index 4ecc0912a4..0000000000
--- a/target-i386/helper.c
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*
- * i386 helpers (without register variable usage)
- *
- * 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 "cpu.h"
-#include "exec/exec-all.h"
-#include "sysemu/kvm.h"
-#include "kvm_i386.h"
-#ifndef CONFIG_USER_ONLY
-#include "sysemu/sysemu.h"
-#include "monitor/monitor.h"
-#include "hw/i386/apic_internal.h"
-#endif
-
-static void cpu_x86_version(CPUX86State *env, int *family, int *model)
-{
- int cpuver = env->cpuid_version;
-
- if (family == NULL || model == NULL) {
- return;
- }
-
- *family = (cpuver >> 8) & 0x0f;
- *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
-}
-
-/* Broadcast MCA signal for processor version 06H_EH and above */
-int cpu_x86_support_mca_broadcast(CPUX86State *env)
-{
- int family = 0;
- int model = 0;
-
- cpu_x86_version(env, &family, &model);
- if ((family == 6 && model >= 14) || family > 6) {
- return 1;
- }
-
- return 0;
-}
-
-/***********************************************************/
-/* x86 debug */
-
-static const char *cc_op_str[CC_OP_NB] = {
- "DYNAMIC",
- "EFLAGS",
-
- "MULB",
- "MULW",
- "MULL",
- "MULQ",
-
- "ADDB",
- "ADDW",
- "ADDL",
- "ADDQ",
-
- "ADCB",
- "ADCW",
- "ADCL",
- "ADCQ",
-
- "SUBB",
- "SUBW",
- "SUBL",
- "SUBQ",
-
- "SBBB",
- "SBBW",
- "SBBL",
- "SBBQ",
-
- "LOGICB",
- "LOGICW",
- "LOGICL",
- "LOGICQ",
-
- "INCB",
- "INCW",
- "INCL",
- "INCQ",
-
- "DECB",
- "DECW",
- "DECL",
- "DECQ",
-
- "SHLB",
- "SHLW",
- "SHLL",
- "SHLQ",
-
- "SARB",
- "SARW",
- "SARL",
- "SARQ",
-
- "BMILGB",
- "BMILGW",
- "BMILGL",
- "BMILGQ",
-
- "ADCX",
- "ADOX",
- "ADCOX",
-
- "CLR",
-};
-
-static void
-cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
- const char *name, struct SegmentCache *sc)
-{
-#ifdef TARGET_X86_64
- if (env->hflags & HF_CS64_MASK) {
- cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
- sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
- } else
-#endif
- {
- cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
- (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
- }
-
- if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
- goto done;
-
- cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
- if (sc->flags & DESC_S_MASK) {
- if (sc->flags & DESC_CS_MASK) {
- cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
- ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
- cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
- (sc->flags & DESC_R_MASK) ? 'R' : '-');
- } else {
- cpu_fprintf(f,
- (sc->flags & DESC_B_MASK || env->hflags & HF_LMA_MASK)
- ? "DS " : "DS16");
- cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
- (sc->flags & DESC_W_MASK) ? 'W' : '-');
- }
- cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
- } else {
- static const char *sys_type_name[2][16] = {
- { /* 32 bit mode */
- "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
- "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
- "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
- "CallGate32", "Reserved", "IntGate32", "TrapGate32"
- },
- { /* 64 bit mode */
- "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
- "Reserved", "Reserved", "Reserved", "Reserved",
- "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
- "Reserved", "IntGate64", "TrapGate64"
- }
- };
- cpu_fprintf(f, "%s",
- sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
- [(sc->flags & DESC_TYPE_MASK)
- >> DESC_TYPE_SHIFT]);
- }
-done:
- cpu_fprintf(f, "\n");
-}
-
-#ifndef CONFIG_USER_ONLY
-
-/* ARRAY_SIZE check is not required because
- * DeliveryMode(dm) has a size of 3 bit.
- */
-static inline const char *dm2str(uint32_t dm)
-{
- static const char *str[] = {
- "Fixed",
- "...",
- "SMI",
- "...",
- "NMI",
- "INIT",
- "...",
- "ExtINT"
- };
- return str[dm];
-}
-
-static void dump_apic_lvt(FILE *f, fprintf_function cpu_fprintf,
- const char *name, uint32_t lvt, bool is_timer)
-{
- uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
- cpu_fprintf(f,
- "%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
- name, lvt,
- lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
- lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
- lvt & APIC_LVT_MASKED ? "masked" : "",
- lvt & APIC_LVT_DELIV_STS ? "pending" : "",
- !is_timer ?
- "" : lvt & APIC_LVT_TIMER_PERIODIC ?
- "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
- "tsc-deadline" : "one-shot",
- dm2str(dm));
- if (dm != APIC_DM_NMI) {
- cpu_fprintf(f, " (vec %u)\n", lvt & APIC_VECTOR_MASK);
- } else {
- cpu_fprintf(f, "\n");
- }
-}
-
-/* ARRAY_SIZE check is not required because
- * destination shorthand has a size of 2 bit.
- */
-static inline const char *shorthand2str(uint32_t shorthand)
-{
- const char *str[] = {
- "no-shorthand", "self", "all-self", "all"
- };
- return str[shorthand];
-}
-
-static inline uint8_t divider_conf(uint32_t divide_conf)
-{
- uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
-
- return divide_val == 7 ? 1 : 2 << divide_val;
-}
-
-static inline void mask2str(char *str, uint32_t val, uint8_t size)
-{
- while (size--) {
- *str++ = (val >> size) & 1 ? '1' : '0';
- }
- *str = 0;
-}
-
-#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
-
-static void dump_apic_icr(FILE *f, fprintf_function cpu_fprintf,
- APICCommonState *s, CPUX86State *env)
-{
- uint32_t icr = s->icr[0], icr2 = s->icr[1];
- uint8_t dest_shorthand = \
- (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
- bool logical_mod = icr & APIC_ICR_DEST_MOD;
- char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
- uint32_t dest_field;
- bool x2apic;
-
- cpu_fprintf(f, "ICR\t 0x%08x %s %s %s %s\n",
- icr,
- logical_mod ? "logical" : "physical",
- icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
- icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
- shorthand2str(dest_shorthand));
-
- cpu_fprintf(f, "ICR2\t 0x%08x", icr2);
- if (dest_shorthand != 0) {
- cpu_fprintf(f, "\n");
- return;
- }
- x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
- dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
-
- if (!logical_mod) {
- if (x2apic) {
- cpu_fprintf(f, " cpu %u (X2APIC ID)\n", dest_field);
- } else {
- cpu_fprintf(f, " cpu %u (APIC ID)\n",
- dest_field & APIC_LOGDEST_XAPIC_ID);
- }
- return;
- }
-
- if (s->dest_mode == 0xf) { /* flat mode */
- mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
- cpu_fprintf(f, " mask %s (APIC ID)\n", apic_id_str);
- } else if (s->dest_mode == 0) { /* cluster mode */
- if (x2apic) {
- mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
- cpu_fprintf(f, " cluster %u mask %s (X2APIC ID)\n",
- dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
- } else {
- mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
- cpu_fprintf(f, " cluster %u mask %s (APIC ID)\n",
- dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
- }
- }
-}
-
-static void dump_apic_interrupt(FILE *f, fprintf_function cpu_fprintf,
- const char *name, uint32_t *ireg_tab,
- uint32_t *tmr_tab)
-{
- int i, empty = true;
-
- cpu_fprintf(f, "%s\t ", name);
- for (i = 0; i < 256; i++) {
- if (apic_get_bit(ireg_tab, i)) {
- cpu_fprintf(f, "%u%s ", i,
- apic_get_bit(tmr_tab, i) ? "(level)" : "");
- empty = false;
- }
- }
- cpu_fprintf(f, "%s\n", empty ? "(none)" : "");
-}
-
-void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
- fprintf_function cpu_fprintf, int flags)
-{
- X86CPU *cpu = X86_CPU(cs);
- APICCommonState *s = APIC_COMMON(cpu->apic_state);
- uint32_t *lvt = s->lvt;
-
- cpu_fprintf(f, "dumping local APIC state for CPU %-2u\n\n",
- CPU(cpu)->cpu_index);
- dump_apic_lvt(f, cpu_fprintf, "LVT0", lvt[APIC_LVT_LINT0], false);
- dump_apic_lvt(f, cpu_fprintf, "LVT1", lvt[APIC_LVT_LINT1], false);
- dump_apic_lvt(f, cpu_fprintf, "LVTPC", lvt[APIC_LVT_PERFORM], false);
- dump_apic_lvt(f, cpu_fprintf, "LVTERR", lvt[APIC_LVT_ERROR], false);
- dump_apic_lvt(f, cpu_fprintf, "LVTTHMR", lvt[APIC_LVT_THERMAL], false);
- dump_apic_lvt(f, cpu_fprintf, "LVTT", lvt[APIC_LVT_TIMER], true);
-
- cpu_fprintf(f, "Timer\t DCR=0x%x (divide by %u) initial_count = %u\n",
- s->divide_conf & APIC_DCR_MASK,
- divider_conf(s->divide_conf),
- s->initial_count);
-
- cpu_fprintf(f, "SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
- s->spurious_vec,
- s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
- s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
- s->spurious_vec & APIC_VECTOR_MASK);
-
- dump_apic_icr(f, cpu_fprintf, s, &cpu->env);
-
- cpu_fprintf(f, "ESR\t 0x%08x\n", s->esr);
-
- dump_apic_interrupt(f, cpu_fprintf, "ISR", s->isr, s->tmr);
- dump_apic_interrupt(f, cpu_fprintf, "IRR", s->irr, s->tmr);
-
- cpu_fprintf(f, "\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
- s->arb_id, s->tpr, s->dest_mode, s->log_dest);
- if (s->dest_mode == 0) {
- cpu_fprintf(f, "(cluster %u: id %u)",
- s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
- s->log_dest & APIC_LOGDEST_XAPIC_ID);
- }
- cpu_fprintf(f, " PPR 0x%02x\n", apic_get_ppr(s));
-}
-#else
-void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
- fprintf_function cpu_fprintf, int flags)
-{
-}
-#endif /* !CONFIG_USER_ONLY */
-
-#define DUMP_CODE_BYTES_TOTAL 50
-#define DUMP_CODE_BYTES_BACKWARD 20
-
-void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
- int flags)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- int eflags, i, nb;
- char cc_op_name[32];
- static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
-
- eflags = cpu_compute_eflags(env);
-#ifdef TARGET_X86_64
- if (env->hflags & HF_CS64_MASK) {
- cpu_fprintf(f,
- "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
- "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
- "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
- "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
- "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
- env->regs[R_EAX],
- env->regs[R_EBX],
- env->regs[R_ECX],
- env->regs[R_EDX],
- env->regs[R_ESI],
- env->regs[R_EDI],
- env->regs[R_EBP],
- env->regs[R_ESP],
- env->regs[8],
- env->regs[9],
- env->regs[10],
- env->regs[11],
- env->regs[12],
- env->regs[13],
- env->regs[14],
- env->regs[15],
- env->eip, eflags,
- eflags & DF_MASK ? 'D' : '-',
- eflags & CC_O ? 'O' : '-',
- eflags & CC_S ? 'S' : '-',
- eflags & CC_Z ? 'Z' : '-',
- eflags & CC_A ? 'A' : '-',
- eflags & CC_P ? 'P' : '-',
- eflags & CC_C ? 'C' : '-',
- env->hflags & HF_CPL_MASK,
- (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
- (env->a20_mask >> 20) & 1,
- (env->hflags >> HF_SMM_SHIFT) & 1,
- cs->halted);
- } else
-#endif
- {
- cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
- "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
- "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
- (uint32_t)env->regs[R_EAX],
- (uint32_t)env->regs[R_EBX],
- (uint32_t)env->regs[R_ECX],
- (uint32_t)env->regs[R_EDX],
- (uint32_t)env->regs[R_ESI],
- (uint32_t)env->regs[R_EDI],
- (uint32_t)env->regs[R_EBP],
- (uint32_t)env->regs[R_ESP],
- (uint32_t)env->eip, eflags,
- eflags & DF_MASK ? 'D' : '-',
- eflags & CC_O ? 'O' : '-',
- eflags & CC_S ? 'S' : '-',
- eflags & CC_Z ? 'Z' : '-',
- eflags & CC_A ? 'A' : '-',
- eflags & CC_P ? 'P' : '-',
- eflags & CC_C ? 'C' : '-',
- env->hflags & HF_CPL_MASK,
- (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
- (env->a20_mask >> 20) & 1,
- (env->hflags >> HF_SMM_SHIFT) & 1,
- cs->halted);
- }
-
- for(i = 0; i < 6; i++) {
- cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
- &env->segs[i]);
- }
- cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
- cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
-
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
- env->gdt.base, env->gdt.limit);
- cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
- env->idt.base, env->idt.limit);
- cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
- (uint32_t)env->cr[0],
- env->cr[2],
- env->cr[3],
- (uint32_t)env->cr[4]);
- for(i = 0; i < 4; i++)
- cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
- cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
- env->dr[6], env->dr[7]);
- } else
-#endif
- {
- cpu_fprintf(f, "GDT= %08x %08x\n",
- (uint32_t)env->gdt.base, env->gdt.limit);
- cpu_fprintf(f, "IDT= %08x %08x\n",
- (uint32_t)env->idt.base, env->idt.limit);
- cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
- (uint32_t)env->cr[0],
- (uint32_t)env->cr[2],
- (uint32_t)env->cr[3],
- (uint32_t)env->cr[4]);
- for(i = 0; i < 4; i++) {
- cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
- }
- cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
- env->dr[6], env->dr[7]);
- }
- if (flags & CPU_DUMP_CCOP) {
- if ((unsigned)env->cc_op < CC_OP_NB)
- snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
- else
- snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
-#ifdef TARGET_X86_64
- if (env->hflags & HF_CS64_MASK) {
- cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
- env->cc_src, env->cc_dst,
- cc_op_name);
- } else
-#endif
- {
- cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
- (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
- cc_op_name);
- }
- }
- cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
- if (flags & CPU_DUMP_FPU) {
- int fptag;
- fptag = 0;
- for(i = 0; i < 8; i++) {
- fptag |= ((!env->fptags[i]) << i);
- }
- cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
- env->fpuc,
- (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
- env->fpstt,
- fptag,
- env->mxcsr);
- for(i=0;i<8;i++) {
- CPU_LDoubleU u;
- u.d = env->fpregs[i].d;
- cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
- i, u.l.lower, u.l.upper);
- if ((i & 1) == 1)
- cpu_fprintf(f, "\n");
- else
- cpu_fprintf(f, " ");
- }
- if (env->hflags & HF_CS64_MASK)
- nb = 16;
- else
- nb = 8;
- for(i=0;i<nb;i++) {
- cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
- i,
- env->xmm_regs[i].ZMM_L(3),
- env->xmm_regs[i].ZMM_L(2),
- env->xmm_regs[i].ZMM_L(1),
- env->xmm_regs[i].ZMM_L(0));
- if ((i & 1) == 1)
- cpu_fprintf(f, "\n");
- else
- cpu_fprintf(f, " ");
- }
- }
- if (flags & CPU_DUMP_CODE) {
- target_ulong base = env->segs[R_CS].base + env->eip;
- target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
- uint8_t code;
- char codestr[3];
-
- cpu_fprintf(f, "Code=");
- for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
- if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
- snprintf(codestr, sizeof(codestr), "%02x", code);
- } else {
- snprintf(codestr, sizeof(codestr), "??");
- }
- cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
- i == offs ? "<" : "", codestr, i == offs ? ">" : "");
- }
- cpu_fprintf(f, "\n");
- }
-}
-
-/***********************************************************/
-/* x86 mmu */
-/* XXX: add PGE support */
-
-void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
-{
- CPUX86State *env = &cpu->env;
-
- a20_state = (a20_state != 0);
- if (a20_state != ((env->a20_mask >> 20) & 1)) {
- CPUState *cs = CPU(cpu);
-
- qemu_log_mask(CPU_LOG_MMU, "A20 update: a20=%d\n", a20_state);
- /* if the cpu is currently executing code, we must unlink it and
- all the potentially executing TB */
- cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
-
- /* when a20 is changed, all the MMU mappings are invalid, so
- we must flush everything */
- tlb_flush(cs, 1);
- env->a20_mask = ~(1 << 20) | (a20_state << 20);
- }
-}
-
-void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
- int pe_state;
-
- qemu_log_mask(CPU_LOG_MMU, "CR0 update: CR0=0x%08x\n", new_cr0);
- if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
- (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
- tlb_flush(CPU(cpu), 1);
- }
-
-#ifdef TARGET_X86_64
- if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
- (env->efer & MSR_EFER_LME)) {
- /* enter in long mode */
- /* XXX: generate an exception */
- if (!(env->cr[4] & CR4_PAE_MASK))
- return;
- env->efer |= MSR_EFER_LMA;
- env->hflags |= HF_LMA_MASK;
- } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
- (env->efer & MSR_EFER_LMA)) {
- /* exit long mode */
- env->efer &= ~MSR_EFER_LMA;
- env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
- env->eip &= 0xffffffff;
- }
-#endif
- env->cr[0] = new_cr0 | CR0_ET_MASK;
-
- /* update PE flag in hidden flags */
- pe_state = (env->cr[0] & CR0_PE_MASK);
- env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
- /* ensure that ADDSEG is always set in real mode */
- env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
- /* update FPU flags */
- env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
- ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
-}
-
-/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
- the PDPT */
-void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
-
- env->cr[3] = new_cr3;
- if (env->cr[0] & CR0_PG_MASK) {
- qemu_log_mask(CPU_LOG_MMU,
- "CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
- tlb_flush(CPU(cpu), 0);
- }
-}
-
-void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
- uint32_t hflags;
-
-#if defined(DEBUG_MMU)
- printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
-#endif
- if ((new_cr4 ^ env->cr[4]) &
- (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
- CR4_SMEP_MASK | CR4_SMAP_MASK)) {
- tlb_flush(CPU(cpu), 1);
- }
-
- /* Clear bits we're going to recompute. */
- hflags = env->hflags & ~(HF_OSFXSR_MASK | HF_SMAP_MASK);
-
- /* SSE handling */
- if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
- new_cr4 &= ~CR4_OSFXSR_MASK;
- }
- if (new_cr4 & CR4_OSFXSR_MASK) {
- hflags |= HF_OSFXSR_MASK;
- }
-
- if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
- new_cr4 &= ~CR4_SMAP_MASK;
- }
- if (new_cr4 & CR4_SMAP_MASK) {
- hflags |= HF_SMAP_MASK;
- }
-
- if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
- new_cr4 &= ~CR4_PKE_MASK;
- }
-
- env->cr[4] = new_cr4;
- env->hflags = hflags;
-
- cpu_sync_bndcs_hflags(env);
-}
-
-#if defined(CONFIG_USER_ONLY)
-
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
- int is_write, int mmu_idx)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- /* user mode only emulation */
- is_write &= 1;
- env->cr[2] = addr;
- env->error_code = (is_write << PG_ERROR_W_BIT);
- env->error_code |= PG_ERROR_U_MASK;
- cs->exception_index = EXCP0E_PAGE;
- env->exception_is_int = 0;
- env->exception_next_eip = -1;
- return 1;
-}
-
-#else
-
-/* return value:
- * -1 = cannot handle fault
- * 0 = nothing more to do
- * 1 = generate PF fault
- */
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
- int is_write1, int mmu_idx)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- uint64_t ptep, pte;
- target_ulong pde_addr, pte_addr;
- int error_code = 0;
- int is_dirty, prot, page_size, is_write, is_user;
- hwaddr paddr;
- uint64_t rsvd_mask = PG_HI_RSVD_MASK;
- uint32_t page_offset;
- target_ulong vaddr;
-
- is_user = mmu_idx == MMU_USER_IDX;
-#if defined(DEBUG_MMU)
- printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
- addr, is_write1, is_user, env->eip);
-#endif
- is_write = is_write1 & 1;
-
- if (!(env->cr[0] & CR0_PG_MASK)) {
- pte = addr;
-#ifdef TARGET_X86_64
- if (!(env->hflags & HF_LMA_MASK)) {
- /* Without long mode we can only address 32bits in real mode */
- pte = (uint32_t)pte;
- }
-#endif
- prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- page_size = 4096;
- goto do_mapping;
- }
-
- if (!(env->efer & MSR_EFER_NXE)) {
- rsvd_mask |= PG_NX_MASK;
- }
-
- if (env->cr[4] & CR4_PAE_MASK) {
- uint64_t pde, pdpe;
- target_ulong pdpe_addr;
-
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- uint64_t pml4e_addr, pml4e;
- int32_t sext;
-
- /* test virtual address sign extension */
- sext = (int64_t)addr >> 47;
- if (sext != 0 && sext != -1) {
- env->error_code = 0;
- cs->exception_index = EXCP0D_GPF;
- return 1;
- }
-
- pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
- env->a20_mask;
- pml4e = x86_ldq_phys(cs, pml4e_addr);
- if (!(pml4e & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pml4e & (rsvd_mask | PG_PSE_MASK)) {
- goto do_fault_rsvd;
- }
- if (!(pml4e & PG_ACCESSED_MASK)) {
- pml4e |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pml4e_addr, pml4e);
- }
- ptep = pml4e ^ PG_NX_MASK;
- pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
- env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pdpe & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep &= pdpe ^ PG_NX_MASK;
- if (!(pdpe & PG_ACCESSED_MASK)) {
- pdpe |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pdpe_addr, pdpe);
- }
- if (pdpe & PG_PSE_MASK) {
- /* 1 GB page */
- page_size = 1024 * 1024 * 1024;
- pte_addr = pdpe_addr;
- pte = pdpe;
- goto do_check_protect;
- }
- } else
-#endif
- {
- /* XXX: load them when cr3 is loaded ? */
- pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
- env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- rsvd_mask |= PG_HI_USER_MASK;
- if (pdpe & (rsvd_mask | PG_NX_MASK)) {
- goto do_fault_rsvd;
- }
- ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
- }
-
- pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
- env->a20_mask;
- pde = x86_ldq_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pde & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep &= pde ^ PG_NX_MASK;
- if (pde & PG_PSE_MASK) {
- /* 2 MB page */
- page_size = 2048 * 1024;
- pte_addr = pde_addr;
- pte = pde;
- goto do_check_protect;
- }
- /* 4 KB page */
- if (!(pde & PG_ACCESSED_MASK)) {
- pde |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pde_addr, pde);
- }
- pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
- env->a20_mask;
- pte = x86_ldq_phys(cs, pte_addr);
- if (!(pte & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pte & rsvd_mask) {
- goto do_fault_rsvd;
- }
- /* combine pde and pte nx, user and rw protections */
- ptep &= pte ^ PG_NX_MASK;
- page_size = 4096;
- } else {
- uint32_t pde;
-
- /* page directory entry */
- pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
- env->a20_mask;
- pde = x86_ldl_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- ptep = pde | PG_NX_MASK;
-
- /* if PSE bit is set, then we use a 4MB page */
- if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
- page_size = 4096 * 1024;
- pte_addr = pde_addr;
-
- /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved.
- * Leave bits 20-13 in place for setting accessed/dirty bits below.
- */
- pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
- rsvd_mask = 0x200000;
- goto do_check_protect_pse36;
- }
-
- if (!(pde & PG_ACCESSED_MASK)) {
- pde |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pde_addr, pde);
- }
-
- /* page directory entry */
- pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
- env->a20_mask;
- pte = x86_ldl_phys(cs, pte_addr);
- if (!(pte & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- /* combine pde and pte user and rw protections */
- ptep &= pte | PG_NX_MASK;
- page_size = 4096;
- rsvd_mask = 0;
- }
-
-do_check_protect:
- rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK;
-do_check_protect_pse36:
- if (pte & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep ^= PG_NX_MASK;
-
- /* can the page can be put in the TLB? prot will tell us */
- if (is_user && !(ptep & PG_USER_MASK)) {
- goto do_fault_protect;
- }
-
- prot = 0;
- if (mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
- prot |= PAGE_READ;
- if ((ptep & PG_RW_MASK) || (!is_user && !(env->cr[0] & CR0_WP_MASK))) {
- prot |= PAGE_WRITE;
- }
- }
- if (!(ptep & PG_NX_MASK) &&
- (mmu_idx == MMU_USER_IDX ||
- !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
- prot |= PAGE_EXEC;
- }
- if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
- (ptep & PG_USER_MASK) && env->pkru) {
- uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
- uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
- uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
- uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-
- if (pkru_ad) {
- pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
- } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
- pkru_prot &= ~PAGE_WRITE;
- }
-
- prot &= pkru_prot;
- if ((pkru_prot & (1 << is_write1)) == 0) {
- assert(is_write1 != 2);
- error_code |= PG_ERROR_PK_MASK;
- goto do_fault_protect;
- }
- }
-
- if ((prot & (1 << is_write1)) == 0) {
- goto do_fault_protect;
- }
-
- /* yes, it can! */
- is_dirty = is_write && !(pte & PG_DIRTY_MASK);
- if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
- pte |= PG_ACCESSED_MASK;
- if (is_dirty) {
- pte |= PG_DIRTY_MASK;
- }
- x86_stl_phys_notdirty(cs, pte_addr, pte);
- }
-
- if (!(pte & PG_DIRTY_MASK)) {
- /* only set write access if already dirty... otherwise wait
- for dirty access */
- assert(!is_write);
- prot &= ~PAGE_WRITE;
- }
-
- do_mapping:
- pte = pte & env->a20_mask;
-
- /* align to page_size */
- pte &= PG_ADDRESS_MASK & ~(page_size - 1);
-
- /* Even if 4MB pages, we map only one 4KB page in the cache to
- avoid filling it too fast */
- vaddr = addr & TARGET_PAGE_MASK;
- page_offset = vaddr & (page_size - 1);
- paddr = pte + page_offset;
-
- assert(prot & (1 << is_write1));
- tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env),
- prot, mmu_idx, page_size);
- return 0;
- do_fault_rsvd:
- error_code |= PG_ERROR_RSVD_MASK;
- do_fault_protect:
- error_code |= PG_ERROR_P_MASK;
- do_fault:
- error_code |= (is_write << PG_ERROR_W_BIT);
- if (is_user)
- error_code |= PG_ERROR_U_MASK;
- if (is_write1 == 2 &&
- (((env->efer & MSR_EFER_NXE) &&
- (env->cr[4] & CR4_PAE_MASK)) ||
- (env->cr[4] & CR4_SMEP_MASK)))
- error_code |= PG_ERROR_I_D_MASK;
- if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
- /* cr2 is not modified in case of exceptions */
- x86_stq_phys(cs,
- env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
- addr);
- } else {
- env->cr[2] = addr;
- }
- env->error_code = error_code;
- cs->exception_index = EXCP0E_PAGE;
- return 1;
-}
-
-hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- target_ulong pde_addr, pte_addr;
- uint64_t pte;
- uint32_t page_offset;
- int page_size;
-
- if (!(env->cr[0] & CR0_PG_MASK)) {
- pte = addr & env->a20_mask;
- page_size = 4096;
- } else if (env->cr[4] & CR4_PAE_MASK) {
- target_ulong pdpe_addr;
- uint64_t pde, pdpe;
-
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- uint64_t pml4e_addr, pml4e;
- int32_t sext;
-
- /* test virtual address sign extension */
- sext = (int64_t)addr >> 47;
- if (sext != 0 && sext != -1) {
- return -1;
- }
- pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
- env->a20_mask;
- pml4e = x86_ldq_phys(cs, pml4e_addr);
- if (!(pml4e & PG_PRESENT_MASK)) {
- return -1;
- }
- pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
- (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK)) {
- return -1;
- }
- if (pdpe & PG_PSE_MASK) {
- page_size = 1024 * 1024 * 1024;
- pte = pdpe;
- goto out;
- }
-
- } else
-#endif
- {
- pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
- env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK))
- return -1;
- }
-
- pde_addr = ((pdpe & PG_ADDRESS_MASK) +
- (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
- pde = x86_ldq_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK)) {
- return -1;
- }
- if (pde & PG_PSE_MASK) {
- /* 2 MB page */
- page_size = 2048 * 1024;
- pte = pde;
- } else {
- /* 4 KB page */
- pte_addr = ((pde & PG_ADDRESS_MASK) +
- (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
- page_size = 4096;
- pte = x86_ldq_phys(cs, pte_addr);
- }
- if (!(pte & PG_PRESENT_MASK)) {
- return -1;
- }
- } else {
- uint32_t pde;
-
- /* page directory entry */
- pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
- pde = x86_ldl_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK))
- return -1;
- if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
- pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
- page_size = 4096 * 1024;
- } else {
- /* page directory entry */
- pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
- pte = x86_ldl_phys(cs, pte_addr);
- if (!(pte & PG_PRESENT_MASK)) {
- return -1;
- }
- page_size = 4096;
- }
- pte = pte & env->a20_mask;
- }
-
-#ifdef TARGET_X86_64
-out:
-#endif
- pte &= PG_ADDRESS_MASK & ~(page_size - 1);
- page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
- return pte | page_offset;
-}
-
-typedef struct MCEInjectionParams {
- Monitor *mon;
- int bank;
- uint64_t status;
- uint64_t mcg_status;
- uint64_t addr;
- uint64_t misc;
- int flags;
-} MCEInjectionParams;
-
-static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
-{
- MCEInjectionParams *params = data.host_ptr;
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *cenv = &cpu->env;
- uint64_t *banks = cenv->mce_banks + 4 * params->bank;
-
- cpu_synchronize_state(cs);
-
- /*
- * If there is an MCE exception being processed, ignore this SRAO MCE
- * unless unconditional injection was requested.
- */
- if (!(params->flags & MCE_INJECT_UNCOND_AO)
- && !(params->status & MCI_STATUS_AR)
- && (cenv->mcg_status & MCG_STATUS_MCIP)) {
- return;
- }
-
- if (params->status & MCI_STATUS_UC) {
- /*
- * if MSR_MCG_CTL is not all 1s, the uncorrected error
- * reporting is disabled
- */
- if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
- monitor_printf(params->mon,
- "CPU %d: Uncorrected error reporting disabled\n",
- cs->cpu_index);
- return;
- }
-
- /*
- * if MSR_MCi_CTL is not all 1s, the uncorrected error
- * reporting is disabled for the bank
- */
- if (banks[0] != ~(uint64_t)0) {
- monitor_printf(params->mon,
- "CPU %d: Uncorrected error reporting disabled for"
- " bank %d\n",
- cs->cpu_index, params->bank);
- return;
- }
-
- if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
- !(cenv->cr[4] & CR4_MCE_MASK)) {
- monitor_printf(params->mon,
- "CPU %d: Previous MCE still in progress, raising"
- " triple fault\n",
- cs->cpu_index);
- qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
- qemu_system_reset_request();
- return;
- }
- if (banks[1] & MCI_STATUS_VAL) {
- params->status |= MCI_STATUS_OVER;
- }
- banks[2] = params->addr;
- banks[3] = params->misc;
- cenv->mcg_status = params->mcg_status;
- banks[1] = params->status;
- cpu_interrupt(cs, CPU_INTERRUPT_MCE);
- } else if (!(banks[1] & MCI_STATUS_VAL)
- || !(banks[1] & MCI_STATUS_UC)) {
- if (banks[1] & MCI_STATUS_VAL) {
- params->status |= MCI_STATUS_OVER;
- }
- banks[2] = params->addr;
- banks[3] = params->misc;
- banks[1] = params->status;
- } else {
- banks[1] |= MCI_STATUS_OVER;
- }
-}
-
-void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
- uint64_t status, uint64_t mcg_status, uint64_t addr,
- uint64_t misc, int flags)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *cenv = &cpu->env;
- MCEInjectionParams params = {
- .mon = mon,
- .bank = bank,
- .status = status,
- .mcg_status = mcg_status,
- .addr = addr,
- .misc = misc,
- .flags = flags,
- };
- unsigned bank_num = cenv->mcg_cap & 0xff;
-
- if (!cenv->mcg_cap) {
- monitor_printf(mon, "MCE injection not supported\n");
- return;
- }
- if (bank >= bank_num) {
- monitor_printf(mon, "Invalid MCE bank number\n");
- return;
- }
- if (!(status & MCI_STATUS_VAL)) {
- monitor_printf(mon, "Invalid MCE status code\n");
- return;
- }
- if ((flags & MCE_INJECT_BROADCAST)
- && !cpu_x86_support_mca_broadcast(cenv)) {
- monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
- return;
- }
-
- run_on_cpu(cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
- if (flags & MCE_INJECT_BROADCAST) {
- CPUState *other_cs;
-
- params.bank = 1;
- params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
- params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
- params.addr = 0;
- params.misc = 0;
- CPU_FOREACH(other_cs) {
- if (other_cs == cs) {
- continue;
- }
- run_on_cpu(other_cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
- }
- }
-}
-
-void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
- CPUState *cs = CPU(cpu);
-
- if (kvm_enabled()) {
- env->tpr_access_type = access;
-
- cpu_interrupt(cs, CPU_INTERRUPT_TPR);
- } else {
- cpu_restore_state(cs, cs->mem_io_pc);
-
- apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
- }
-}
-#endif /* !CONFIG_USER_ONLY */
-
-int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
- target_ulong *base, unsigned int *limit,
- unsigned int *flags)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
- CPUState *cs = CPU(cpu);
- SegmentCache *dt;
- target_ulong ptr;
- uint32_t e1, e2;
- int index;
-
- if (selector & 0x4)
- dt = &env->ldt;
- else
- dt = &env->gdt;
- index = selector & ~7;
- ptr = dt->base + index;
- if ((index + 7) > dt->limit
- || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
- || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
- return 0;
-
- *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
- *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
- if (e2 & DESC_G_MASK)
- *limit = (*limit << 12) | 0xfff;
- *flags = e2;
-
- return 1;
-}
-
-#if !defined(CONFIG_USER_ONLY)
-void do_cpu_init(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- CPUX86State *save = g_new(CPUX86State, 1);
- int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
-
- *save = *env;
-
- cpu_reset(cs);
- cs->interrupt_request = sipi;
- memcpy(&env->start_init_save, &save->start_init_save,
- offsetof(CPUX86State, end_init_save) -
- offsetof(CPUX86State, start_init_save));
- g_free(save);
-
- if (kvm_enabled()) {
- kvm_arch_do_init_vcpu(cpu);
- }
- apic_init_reset(cpu->apic_state);
-}
-
-void do_cpu_sipi(X86CPU *cpu)
-{
- apic_sipi(cpu->apic_state);
-}
-#else
-void do_cpu_init(X86CPU *cpu)
-{
-}
-void do_cpu_sipi(X86CPU *cpu)
-{
-}
-#endif
-
-/* Frob eflags into and out of the CPU temporary format. */
-
-void x86_cpu_exec_enter(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
- env->df = 1 - (2 * ((env->eflags >> 10) & 1));
- CC_OP = CC_OP_EFLAGS;
- env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-}
-
-void x86_cpu_exec_exit(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- env->eflags = cpu_compute_eflags(env);
-}
-
-#ifndef CONFIG_USER_ONLY
-uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return address_space_ldub(cs->as, addr,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return address_space_lduw(cs->as, addr,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return address_space_ldl(cs->as, addr,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return address_space_ldq(cs->as, addr,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- address_space_stb(cs->as, addr, val,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- address_space_stl_notdirty(cs->as, addr, val,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- address_space_stw(cs->as, addr, val,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- address_space_stl(cs->as, addr, val,
- cpu_get_mem_attrs(env),
- NULL);
-}
-
-void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- address_space_stq(cs->as, addr, val,
- cpu_get_mem_attrs(env),
- NULL);
-}
-#endif
diff --git a/target-i386/helper.h b/target-i386/helper.h
deleted file mode 100644
index 4e859eba9d..0000000000
--- a/target-i386/helper.h
+++ /dev/null
@@ -1,230 +0,0 @@
-DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
-DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
-
-DEF_HELPER_3(write_eflags, void, env, tl, i32)
-DEF_HELPER_1(read_eflags, tl, env)
-DEF_HELPER_2(divb_AL, void, env, tl)
-DEF_HELPER_2(idivb_AL, void, env, tl)
-DEF_HELPER_2(divw_AX, void, env, tl)
-DEF_HELPER_2(idivw_AX, void, env, tl)
-DEF_HELPER_2(divl_EAX, void, env, tl)
-DEF_HELPER_2(idivl_EAX, void, env, tl)
-#ifdef TARGET_X86_64
-DEF_HELPER_2(divq_EAX, void, env, tl)
-DEF_HELPER_2(idivq_EAX, void, env, tl)
-#endif
-DEF_HELPER_FLAGS_2(cr4_testbit, TCG_CALL_NO_WG, void, env, i32)
-
-DEF_HELPER_FLAGS_2(bndck, TCG_CALL_NO_WG, void, env, i32)
-DEF_HELPER_FLAGS_3(bndldx32, TCG_CALL_NO_WG, i64, env, tl, tl)
-DEF_HELPER_FLAGS_3(bndldx64, TCG_CALL_NO_WG, i64, env, tl, tl)
-DEF_HELPER_FLAGS_5(bndstx32, TCG_CALL_NO_WG, void, env, tl, tl, i64, i64)
-DEF_HELPER_FLAGS_5(bndstx64, TCG_CALL_NO_WG, void, env, tl, tl, i64, i64)
-DEF_HELPER_1(bnd_jmp, void, env)
-
-DEF_HELPER_2(aam, void, env, int)
-DEF_HELPER_2(aad, void, env, int)
-DEF_HELPER_1(aaa, void, env)
-DEF_HELPER_1(aas, void, env)
-DEF_HELPER_1(daa, void, env)
-DEF_HELPER_1(das, void, env)
-
-DEF_HELPER_2(lsl, tl, env, tl)
-DEF_HELPER_2(lar, tl, env, tl)
-DEF_HELPER_2(verr, void, env, tl)
-DEF_HELPER_2(verw, void, env, tl)
-DEF_HELPER_2(lldt, void, env, int)
-DEF_HELPER_2(ltr, void, env, int)
-DEF_HELPER_3(load_seg, void, env, int, int)
-DEF_HELPER_4(ljmp_protected, void, env, int, tl, tl)
-DEF_HELPER_5(lcall_real, void, env, int, tl, int, int)
-DEF_HELPER_5(lcall_protected, void, env, int, tl, int, tl)
-DEF_HELPER_2(iret_real, void, env, int)
-DEF_HELPER_3(iret_protected, void, env, int, int)
-DEF_HELPER_3(lret_protected, void, env, int, int)
-DEF_HELPER_2(read_crN, tl, env, int)
-DEF_HELPER_3(write_crN, void, env, int, tl)
-DEF_HELPER_2(lmsw, void, env, tl)
-DEF_HELPER_1(clts, void, env)
-DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
-DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
-DEF_HELPER_2(invlpg, void, env, tl)
-
-DEF_HELPER_1(sysenter, void, env)
-DEF_HELPER_2(sysexit, void, env, int)
-#ifdef TARGET_X86_64
-DEF_HELPER_2(syscall, void, env, int)
-DEF_HELPER_2(sysret, void, env, int)
-#endif
-DEF_HELPER_2(hlt, void, env, int)
-DEF_HELPER_2(monitor, void, env, tl)
-DEF_HELPER_2(mwait, void, env, int)
-DEF_HELPER_2(pause, void, env, int)
-DEF_HELPER_1(debug, void, env)
-DEF_HELPER_1(reset_rf, void, env)
-DEF_HELPER_3(raise_interrupt, void, env, int, int)
-DEF_HELPER_2(raise_exception, void, env, int)
-DEF_HELPER_1(cli, void, env)
-DEF_HELPER_1(sti, void, env)
-DEF_HELPER_1(clac, void, env)
-DEF_HELPER_1(stac, void, env)
-DEF_HELPER_3(boundw, void, env, tl, int)
-DEF_HELPER_3(boundl, void, env, tl, int)
-DEF_HELPER_1(rsm, void, env)
-DEF_HELPER_2(into, void, env, int)
-DEF_HELPER_2(cmpxchg8b_unlocked, void, env, tl)
-DEF_HELPER_2(cmpxchg8b, void, env, tl)
-#ifdef TARGET_X86_64
-DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl)
-DEF_HELPER_2(cmpxchg16b, void, env, tl)
-#endif
-DEF_HELPER_1(single_step, void, env)
-DEF_HELPER_1(cpuid, void, env)
-DEF_HELPER_1(rdtsc, void, env)
-DEF_HELPER_1(rdtscp, void, env)
-DEF_HELPER_1(rdpmc, void, env)
-DEF_HELPER_1(rdmsr, void, env)
-DEF_HELPER_1(wrmsr, void, env)
-
-DEF_HELPER_2(check_iob, void, env, i32)
-DEF_HELPER_2(check_iow, void, env, i32)
-DEF_HELPER_2(check_iol, void, env, i32)
-DEF_HELPER_3(outb, void, env, i32, i32)
-DEF_HELPER_2(inb, tl, env, i32)
-DEF_HELPER_3(outw, void, env, i32, i32)
-DEF_HELPER_2(inw, tl, env, i32)
-DEF_HELPER_3(outl, void, env, i32, i32)
-DEF_HELPER_2(inl, tl, env, i32)
-DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
-
-DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
-DEF_HELPER_3(vmexit, void, env, i32, i64)
-DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
-DEF_HELPER_3(vmrun, void, env, int, int)
-DEF_HELPER_1(vmmcall, void, env)
-DEF_HELPER_2(vmload, void, env, int)
-DEF_HELPER_2(vmsave, void, env, int)
-DEF_HELPER_1(stgi, void, env)
-DEF_HELPER_1(clgi, void, env)
-DEF_HELPER_1(skinit, void, env)
-DEF_HELPER_2(invlpga, void, env, int)
-
-/* x86 FPU */
-
-DEF_HELPER_2(flds_FT0, void, env, i32)
-DEF_HELPER_2(fldl_FT0, void, env, i64)
-DEF_HELPER_2(fildl_FT0, void, env, s32)
-DEF_HELPER_2(flds_ST0, void, env, i32)
-DEF_HELPER_2(fldl_ST0, void, env, i64)
-DEF_HELPER_2(fildl_ST0, void, env, s32)
-DEF_HELPER_2(fildll_ST0, void, env, s64)
-DEF_HELPER_1(fsts_ST0, i32, env)
-DEF_HELPER_1(fstl_ST0, i64, env)
-DEF_HELPER_1(fist_ST0, s32, env)
-DEF_HELPER_1(fistl_ST0, s32, env)
-DEF_HELPER_1(fistll_ST0, s64, env)
-DEF_HELPER_1(fistt_ST0, s32, env)
-DEF_HELPER_1(fisttl_ST0, s32, env)
-DEF_HELPER_1(fisttll_ST0, s64, env)
-DEF_HELPER_2(fldt_ST0, void, env, tl)
-DEF_HELPER_2(fstt_ST0, void, env, tl)
-DEF_HELPER_1(fpush, void, env)
-DEF_HELPER_1(fpop, void, env)
-DEF_HELPER_1(fdecstp, void, env)
-DEF_HELPER_1(fincstp, void, env)
-DEF_HELPER_2(ffree_STN, void, env, int)
-DEF_HELPER_1(fmov_ST0_FT0, void, env)
-DEF_HELPER_2(fmov_FT0_STN, void, env, int)
-DEF_HELPER_2(fmov_ST0_STN, void, env, int)
-DEF_HELPER_2(fmov_STN_ST0, void, env, int)
-DEF_HELPER_2(fxchg_ST0_STN, void, env, int)
-DEF_HELPER_1(fcom_ST0_FT0, void, env)
-DEF_HELPER_1(fucom_ST0_FT0, void, env)
-DEF_HELPER_1(fcomi_ST0_FT0, void, env)
-DEF_HELPER_1(fucomi_ST0_FT0, void, env)
-DEF_HELPER_1(fadd_ST0_FT0, void, env)
-DEF_HELPER_1(fmul_ST0_FT0, void, env)
-DEF_HELPER_1(fsub_ST0_FT0, void, env)
-DEF_HELPER_1(fsubr_ST0_FT0, void, env)
-DEF_HELPER_1(fdiv_ST0_FT0, void, env)
-DEF_HELPER_1(fdivr_ST0_FT0, void, env)
-DEF_HELPER_2(fadd_STN_ST0, void, env, int)
-DEF_HELPER_2(fmul_STN_ST0, void, env, int)
-DEF_HELPER_2(fsub_STN_ST0, void, env, int)
-DEF_HELPER_2(fsubr_STN_ST0, void, env, int)
-DEF_HELPER_2(fdiv_STN_ST0, void, env, int)
-DEF_HELPER_2(fdivr_STN_ST0, void, env, int)
-DEF_HELPER_1(fchs_ST0, void, env)
-DEF_HELPER_1(fabs_ST0, void, env)
-DEF_HELPER_1(fxam_ST0, void, env)
-DEF_HELPER_1(fld1_ST0, void, env)
-DEF_HELPER_1(fldl2t_ST0, void, env)
-DEF_HELPER_1(fldl2e_ST0, void, env)
-DEF_HELPER_1(fldpi_ST0, void, env)
-DEF_HELPER_1(fldlg2_ST0, void, env)
-DEF_HELPER_1(fldln2_ST0, void, env)
-DEF_HELPER_1(fldz_ST0, void, env)
-DEF_HELPER_1(fldz_FT0, void, env)
-DEF_HELPER_1(fnstsw, i32, env)
-DEF_HELPER_1(fnstcw, i32, env)
-DEF_HELPER_2(fldcw, void, env, i32)
-DEF_HELPER_1(fclex, void, env)
-DEF_HELPER_1(fwait, void, env)
-DEF_HELPER_1(fninit, void, env)
-DEF_HELPER_2(fbld_ST0, void, env, tl)
-DEF_HELPER_2(fbst_ST0, void, env, tl)
-DEF_HELPER_1(f2xm1, void, env)
-DEF_HELPER_1(fyl2x, void, env)
-DEF_HELPER_1(fptan, void, env)
-DEF_HELPER_1(fpatan, void, env)
-DEF_HELPER_1(fxtract, void, env)
-DEF_HELPER_1(fprem1, void, env)
-DEF_HELPER_1(fprem, void, env)
-DEF_HELPER_1(fyl2xp1, void, env)
-DEF_HELPER_1(fsqrt, void, env)
-DEF_HELPER_1(fsincos, void, env)
-DEF_HELPER_1(frndint, void, env)
-DEF_HELPER_1(fscale, void, env)
-DEF_HELPER_1(fsin, void, env)
-DEF_HELPER_1(fcos, void, env)
-DEF_HELPER_3(fstenv, void, env, tl, int)
-DEF_HELPER_3(fldenv, void, env, tl, int)
-DEF_HELPER_3(fsave, void, env, tl, int)
-DEF_HELPER_3(frstor, void, env, tl, int)
-DEF_HELPER_FLAGS_2(fxsave, TCG_CALL_NO_WG, void, env, tl)
-DEF_HELPER_FLAGS_2(fxrstor, TCG_CALL_NO_WG, void, env, tl)
-DEF_HELPER_FLAGS_3(xsave, TCG_CALL_NO_WG, void, env, tl, i64)
-DEF_HELPER_FLAGS_3(xsaveopt, TCG_CALL_NO_WG, void, env, tl, i64)
-DEF_HELPER_FLAGS_3(xrstor, TCG_CALL_NO_WG, void, env, tl, i64)
-DEF_HELPER_FLAGS_2(xgetbv, TCG_CALL_NO_WG, i64, env, i32)
-DEF_HELPER_FLAGS_3(xsetbv, TCG_CALL_NO_WG, void, env, i32, i64)
-DEF_HELPER_FLAGS_2(rdpkru, TCG_CALL_NO_WG, i64, env, i32)
-DEF_HELPER_FLAGS_3(wrpkru, TCG_CALL_NO_WG, void, env, i32, i64)
-
-DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_FLAGS_1(ctz, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_FLAGS_2(pdep, TCG_CALL_NO_RWG_SE, tl, tl, tl)
-DEF_HELPER_FLAGS_2(pext, TCG_CALL_NO_RWG_SE, tl, tl, tl)
-
-/* MMX/SSE */
-
-DEF_HELPER_2(ldmxcsr, void, env, i32)
-DEF_HELPER_1(enter_mmx, void, env)
-DEF_HELPER_1(emms, void, env)
-DEF_HELPER_3(movq, void, env, ptr, ptr)
-
-#define SHIFT 0
-#include "ops_sse_header.h"
-#define SHIFT 1
-#include "ops_sse_header.h"
-
-DEF_HELPER_3(rclb, tl, env, tl, tl)
-DEF_HELPER_3(rclw, tl, env, tl, tl)
-DEF_HELPER_3(rcll, tl, env, tl, tl)
-DEF_HELPER_3(rcrb, tl, env, tl, tl)
-DEF_HELPER_3(rcrw, tl, env, tl, tl)
-DEF_HELPER_3(rcrl, tl, env, tl, tl)
-#ifdef TARGET_X86_64
-DEF_HELPER_3(rclq, tl, env, tl, tl)
-DEF_HELPER_3(rcrq, tl, env, tl, tl)
-#endif
diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c
deleted file mode 100644
index 39a230f119..0000000000
--- a/target-i386/hyperv.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * QEMU KVM Hyper-V support
- *
- * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * Authors:
- * Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hyperv.h"
-#include "standard-headers/asm-x86/hyperv.h"
-
-int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
-{
- CPUX86State *env = &cpu->env;
-
- switch (exit->type) {
- case KVM_EXIT_HYPERV_SYNIC:
- if (!cpu->hyperv_synic) {
- return -1;
- }
-
- /*
- * For now just track changes in SynIC control and msg/evt pages msr's.
- * When SynIC messaging/events processing will be added in future
- * here we will do messages queues flushing and pages remapping.
- */
- switch (exit->u.synic.msr) {
- case HV_X64_MSR_SCONTROL:
- env->msr_hv_synic_control = exit->u.synic.control;
- break;
- case HV_X64_MSR_SIMP:
- env->msr_hv_synic_msg_page = exit->u.synic.msg_page;
- break;
- case HV_X64_MSR_SIEFP:
- env->msr_hv_synic_evt_page = exit->u.synic.evt_page;
- break;
- default:
- return -1;
- }
- return 0;
- case KVM_EXIT_HYPERV_HCALL: {
- uint16_t code;
-
- code = exit->u.hcall.input & 0xffff;
- switch (code) {
- case HVCALL_POST_MESSAGE:
- case HVCALL_SIGNAL_EVENT:
- default:
- exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE;
- return 0;
- }
- }
- default:
- return -1;
- }
-}
-
-static void kvm_hv_sint_ack_handler(EventNotifier *notifier)
-{
- HvSintRoute *sint_route = container_of(notifier, HvSintRoute,
- sint_ack_notifier);
- event_notifier_test_and_clear(notifier);
- if (sint_route->sint_ack_clb) {
- sint_route->sint_ack_clb(sint_route);
- }
-}
-
-HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
- HvSintAckClb sint_ack_clb)
-{
- HvSintRoute *sint_route;
- int r, gsi;
-
- sint_route = g_malloc0(sizeof(*sint_route));
- r = event_notifier_init(&sint_route->sint_set_notifier, false);
- if (r) {
- goto err;
- }
-
- r = event_notifier_init(&sint_route->sint_ack_notifier, false);
- if (r) {
- goto err_sint_set_notifier;
- }
-
- event_notifier_set_handler(&sint_route->sint_ack_notifier, false,
- kvm_hv_sint_ack_handler);
-
- gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
- if (gsi < 0) {
- goto err_gsi;
- }
-
- r = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state,
- &sint_route->sint_set_notifier,
- &sint_route->sint_ack_notifier, gsi);
- if (r) {
- goto err_irqfd;
- }
- sint_route->gsi = gsi;
- sint_route->sint_ack_clb = sint_ack_clb;
- sint_route->vcpu_id = vcpu_id;
- sint_route->sint = sint;
-
- return sint_route;
-
-err_irqfd:
- kvm_irqchip_release_virq(kvm_state, gsi);
-err_gsi:
- event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL);
- event_notifier_cleanup(&sint_route->sint_ack_notifier);
-err_sint_set_notifier:
- event_notifier_cleanup(&sint_route->sint_set_notifier);
-err:
- g_free(sint_route);
-
- return NULL;
-}
-
-void kvm_hv_sint_route_destroy(HvSintRoute *sint_route)
-{
- kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state,
- &sint_route->sint_set_notifier,
- sint_route->gsi);
- kvm_irqchip_release_virq(kvm_state, sint_route->gsi);
- event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL);
- event_notifier_cleanup(&sint_route->sint_ack_notifier);
- event_notifier_cleanup(&sint_route->sint_set_notifier);
- g_free(sint_route);
-}
-
-int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route)
-{
- return event_notifier_set(&sint_route->sint_set_notifier);
-}
diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h
deleted file mode 100644
index 0c3b562018..0000000000
--- a/target-i386/hyperv.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * QEMU KVM Hyper-V support
- *
- * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * Authors:
- * Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef TARGET_I386_HYPERV_H
-#define TARGET_I386_HYPERV_H
-
-#include "cpu.h"
-#include "sysemu/kvm.h"
-#include "qemu/event_notifier.h"
-
-typedef struct HvSintRoute HvSintRoute;
-typedef void (*HvSintAckClb)(HvSintRoute *sint_route);
-
-struct HvSintRoute {
- uint32_t sint;
- uint32_t vcpu_id;
- int gsi;
- EventNotifier sint_set_notifier;
- EventNotifier sint_ack_notifier;
- HvSintAckClb sint_ack_clb;
-};
-
-int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit);
-
-HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
- HvSintAckClb sint_ack_clb);
-
-void kvm_hv_sint_route_destroy(HvSintRoute *sint_route);
-
-int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route);
-
-#endif
diff --git a/target-i386/int_helper.c b/target-i386/int_helper.c
deleted file mode 100644
index 9e873ac150..0000000000
--- a/target-i386/int_helper.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * x86 integer helpers
- *
- * 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 "cpu.h"
-#include "exec/exec-all.h"
-#include "qemu/host-utils.h"
-#include "exec/helper-proto.h"
-
-//#define DEBUG_MULDIV
-
-/* modulo 9 table */
-static const uint8_t rclb_table[32] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 0, 1, 2, 3, 4, 5,
- 6, 7, 8, 0, 1, 2, 3, 4,
-};
-
-/* modulo 17 table */
-static const uint8_t rclw_table[32] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
-};
-
-/* division, flags are undefined */
-
-void helper_divb_AL(CPUX86State *env, target_ulong t0)
-{
- unsigned int num, den, q, r;
-
- num = (env->regs[R_EAX] & 0xffff);
- den = (t0 & 0xff);
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- if (q > 0xff) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q &= 0xff;
- r = (num % den) & 0xff;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q;
-}
-
-void helper_idivb_AL(CPUX86State *env, target_ulong t0)
-{
- int num, den, q, r;
-
- num = (int16_t)env->regs[R_EAX];
- den = (int8_t)t0;
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- if (q != (int8_t)q) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q &= 0xff;
- r = (num % den) & 0xff;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q;
-}
-
-void helper_divw_AX(CPUX86State *env, target_ulong t0)
-{
- unsigned int num, den, q, r;
-
- num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
- den = (t0 & 0xffff);
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- if (q > 0xffff) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q &= 0xffff;
- r = (num % den) & 0xffff;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q;
- env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r;
-}
-
-void helper_idivw_AX(CPUX86State *env, target_ulong t0)
-{
- int num, den, q, r;
-
- num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
- den = (int16_t)t0;
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- if (q != (int16_t)q) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q &= 0xffff;
- r = (num % den) & 0xffff;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q;
- env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r;
-}
-
-void helper_divl_EAX(CPUX86State *env, target_ulong t0)
-{
- unsigned int den, r;
- uint64_t num, q;
-
- num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
- den = t0;
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- r = (num % den);
- if (q > 0xffffffff) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- env->regs[R_EAX] = (uint32_t)q;
- env->regs[R_EDX] = (uint32_t)r;
-}
-
-void helper_idivl_EAX(CPUX86State *env, target_ulong t0)
-{
- int den, r;
- int64_t num, q;
-
- num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
- den = t0;
- if (den == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- q = (num / den);
- r = (num % den);
- if (q != (int32_t)q) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- env->regs[R_EAX] = (uint32_t)q;
- env->regs[R_EDX] = (uint32_t)r;
-}
-
-/* bcd */
-
-/* XXX: exception */
-void helper_aam(CPUX86State *env, int base)
-{
- int al, ah;
-
- al = env->regs[R_EAX] & 0xff;
- ah = al / base;
- al = al % base;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8);
- CC_DST = al;
-}
-
-void helper_aad(CPUX86State *env, int base)
-{
- int al, ah;
-
- al = env->regs[R_EAX] & 0xff;
- ah = (env->regs[R_EAX] >> 8) & 0xff;
- al = ((ah * base) + al) & 0xff;
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al;
- CC_DST = al;
-}
-
-void helper_aaa(CPUX86State *env)
-{
- int icarry;
- int al, ah, af;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- af = eflags & CC_A;
- al = env->regs[R_EAX] & 0xff;
- ah = (env->regs[R_EAX] >> 8) & 0xff;
-
- icarry = (al > 0xf9);
- if (((al & 0x0f) > 9) || af) {
- al = (al + 6) & 0x0f;
- ah = (ah + 1 + icarry) & 0xff;
- eflags |= CC_C | CC_A;
- } else {
- eflags &= ~(CC_C | CC_A);
- al &= 0x0f;
- }
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8);
- CC_SRC = eflags;
-}
-
-void helper_aas(CPUX86State *env)
-{
- int icarry;
- int al, ah, af;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- af = eflags & CC_A;
- al = env->regs[R_EAX] & 0xff;
- ah = (env->regs[R_EAX] >> 8) & 0xff;
-
- icarry = (al < 6);
- if (((al & 0x0f) > 9) || af) {
- al = (al - 6) & 0x0f;
- ah = (ah - 1 - icarry) & 0xff;
- eflags |= CC_C | CC_A;
- } else {
- eflags &= ~(CC_C | CC_A);
- al &= 0x0f;
- }
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8);
- CC_SRC = eflags;
-}
-
-void helper_daa(CPUX86State *env)
-{
- int old_al, al, af, cf;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- cf = eflags & CC_C;
- af = eflags & CC_A;
- old_al = al = env->regs[R_EAX] & 0xff;
-
- eflags = 0;
- if (((al & 0x0f) > 9) || af) {
- al = (al + 6) & 0xff;
- eflags |= CC_A;
- }
- if ((old_al > 0x99) || cf) {
- al = (al + 0x60) & 0xff;
- eflags |= CC_C;
- }
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al;
- /* well, speed is not an issue here, so we compute the flags by hand */
- eflags |= (al == 0) << 6; /* zf */
- eflags |= parity_table[al]; /* pf */
- eflags |= (al & 0x80); /* sf */
- CC_SRC = eflags;
-}
-
-void helper_das(CPUX86State *env)
-{
- int al, al1, af, cf;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- cf = eflags & CC_C;
- af = eflags & CC_A;
- al = env->regs[R_EAX] & 0xff;
-
- eflags = 0;
- al1 = al;
- if (((al & 0x0f) > 9) || af) {
- eflags |= CC_A;
- if (al < 6 || cf) {
- eflags |= CC_C;
- }
- al = (al - 6) & 0xff;
- }
- if ((al1 > 0x99) || cf) {
- al = (al - 0x60) & 0xff;
- eflags |= CC_C;
- }
- env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al;
- /* well, speed is not an issue here, so we compute the flags by hand */
- eflags |= (al == 0) << 6; /* zf */
- eflags |= parity_table[al]; /* pf */
- eflags |= (al & 0x80); /* sf */
- CC_SRC = eflags;
-}
-
-#ifdef TARGET_X86_64
-static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
-{
- *plow += a;
- /* carry test */
- if (*plow < a) {
- (*phigh)++;
- }
- *phigh += b;
-}
-
-static void neg128(uint64_t *plow, uint64_t *phigh)
-{
- *plow = ~*plow;
- *phigh = ~*phigh;
- add128(plow, phigh, 1, 0);
-}
-
-/* return TRUE if overflow */
-static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
-{
- uint64_t q, r, a1, a0;
- int i, qb, ab;
-
- a0 = *plow;
- a1 = *phigh;
- if (a1 == 0) {
- q = a0 / b;
- r = a0 % b;
- *plow = q;
- *phigh = r;
- } else {
- if (a1 >= b) {
- return 1;
- }
- /* XXX: use a better algorithm */
- for (i = 0; i < 64; i++) {
- ab = a1 >> 63;
- a1 = (a1 << 1) | (a0 >> 63);
- if (ab || a1 >= b) {
- a1 -= b;
- qb = 1;
- } else {
- qb = 0;
- }
- a0 = (a0 << 1) | qb;
- }
-#if defined(DEBUG_MULDIV)
- printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64
- ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
- *phigh, *plow, b, a0, a1);
-#endif
- *plow = a0;
- *phigh = a1;
- }
- return 0;
-}
-
-/* return TRUE if overflow */
-static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
-{
- int sa, sb;
-
- sa = ((int64_t)*phigh < 0);
- if (sa) {
- neg128(plow, phigh);
- }
- sb = (b < 0);
- if (sb) {
- b = -b;
- }
- if (div64(plow, phigh, b) != 0) {
- return 1;
- }
- if (sa ^ sb) {
- if (*plow > (1ULL << 63)) {
- return 1;
- }
- *plow = -*plow;
- } else {
- if (*plow >= (1ULL << 63)) {
- return 1;
- }
- }
- if (sa) {
- *phigh = -*phigh;
- }
- return 0;
-}
-
-void helper_divq_EAX(CPUX86State *env, target_ulong t0)
-{
- uint64_t r0, r1;
-
- if (t0 == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- r0 = env->regs[R_EAX];
- r1 = env->regs[R_EDX];
- if (div64(&r0, &r1, t0)) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- env->regs[R_EAX] = r0;
- env->regs[R_EDX] = r1;
-}
-
-void helper_idivq_EAX(CPUX86State *env, target_ulong t0)
-{
- uint64_t r0, r1;
-
- if (t0 == 0) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- r0 = env->regs[R_EAX];
- r1 = env->regs[R_EDX];
- if (idiv64(&r0, &r1, t0)) {
- raise_exception_ra(env, EXCP00_DIVZ, GETPC());
- }
- env->regs[R_EAX] = r0;
- env->regs[R_EDX] = r1;
-}
-#endif
-
-#if TARGET_LONG_BITS == 32
-# define ctztl ctz32
-# define clztl clz32
-#else
-# define ctztl ctz64
-# define clztl clz64
-#endif
-
-/* bit operations */
-target_ulong helper_ctz(target_ulong t0)
-{
- return ctztl(t0);
-}
-
-target_ulong helper_clz(target_ulong t0)
-{
- return clztl(t0);
-}
-
-target_ulong helper_pdep(target_ulong src, target_ulong mask)
-{
- target_ulong dest = 0;
- int i, o;
-
- for (i = 0; mask != 0; i++) {
- o = ctztl(mask);
- mask &= mask - 1;
- dest |= ((src >> i) & 1) << o;
- }
- return dest;
-}
-
-target_ulong helper_pext(target_ulong src, target_ulong mask)
-{
- target_ulong dest = 0;
- int i, o;
-
- for (o = 0; mask != 0; o++) {
- i = ctztl(mask);
- mask &= mask - 1;
- dest |= ((src >> i) & 1) << o;
- }
- return dest;
-}
-
-#define SHIFT 0
-#include "shift_helper_template.h"
-#undef SHIFT
-
-#define SHIFT 1
-#include "shift_helper_template.h"
-#undef SHIFT
-
-#define SHIFT 2
-#include "shift_helper_template.h"
-#undef SHIFT
-
-#ifdef TARGET_X86_64
-#define SHIFT 3
-#include "shift_helper_template.h"
-#undef SHIFT
-#endif
-
-/* Test that BIT is enabled in CR4. If not, raise an illegal opcode
- exception. This reduces the requirements for rare CR4 bits being
- mapped into HFLAGS. */
-void helper_cr4_testbit(CPUX86State *env, uint32_t bit)
-{
- if (unlikely((env->cr[4] & bit) == 0)) {
- raise_exception_ra(env, EXCP06_ILLOP, GETPC());
- }
-}
diff --git a/target-i386/kvm-stub.c b/target-i386/kvm-stub.c
deleted file mode 100644
index bda4dc2f0c..0000000000
--- a/target-i386/kvm-stub.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * QEMU KVM x86 specific function stubs
- *
- * Copyright Linaro Limited 2012
- *
- * Author: Peter Maydell <peter.maydell@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "kvm_i386.h"
-
-bool kvm_allows_irq0_override(void)
-{
- return 1;
-}
-
-#ifndef __OPTIMIZE__
-bool kvm_has_smm(void)
-{
- return 1;
-}
-
-bool kvm_enable_x2apic(void)
-{
- return false;
-}
-
-/* This function is only called inside conditionals which we
- * rely on the compiler to optimize out when CONFIG_KVM is not
- * defined.
- */
-uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
- uint32_t index, int reg)
-{
- abort();
-}
-#endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
deleted file mode 100644
index f62264a7a8..0000000000
--- a/target-i386/kvm.c
+++ /dev/null
@@ -1,3536 +0,0 @@
-/*
- * QEMU KVM support
- *
- * Copyright (C) 2006-2008 Qumranet Technologies
- * Copyright IBM, Corp. 2008
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include <sys/ioctl.h>
-#include <sys/utsname.h>
-
-#include <linux/kvm.h>
-#include <linux/kvm_para.h>
-
-#include "qemu-common.h"
-#include "cpu.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm_int.h"
-#include "kvm_i386.h"
-#include "hyperv.h"
-
-#include "exec/gdbstub.h"
-#include "qemu/host-utils.h"
-#include "qemu/config-file.h"
-#include "qemu/error-report.h"
-#include "hw/i386/pc.h"
-#include "hw/i386/apic.h"
-#include "hw/i386/apic_internal.h"
-#include "hw/i386/apic-msidef.h"
-#include "hw/i386/intel_iommu.h"
-#include "hw/i386/x86-iommu.h"
-
-#include "exec/ioport.h"
-#include "standard-headers/asm-x86/hyperv.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/msi.h"
-#include "migration/migration.h"
-#include "exec/memattrs.h"
-#include "trace.h"
-
-//#define DEBUG_KVM
-
-#ifdef DEBUG_KVM
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
-#define MSR_KVM_WALL_CLOCK 0x11
-#define MSR_KVM_SYSTEM_TIME 0x12
-
-/* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus
- * 255 kvm_msr_entry structs */
-#define MSR_BUF_SIZE 4096
-
-#ifndef BUS_MCEERR_AR
-#define BUS_MCEERR_AR 4
-#endif
-#ifndef BUS_MCEERR_AO
-#define BUS_MCEERR_AO 5
-#endif
-
-const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
- KVM_CAP_INFO(SET_TSS_ADDR),
- KVM_CAP_INFO(EXT_CPUID),
- KVM_CAP_INFO(MP_STATE),
- KVM_CAP_LAST_INFO
-};
-
-static bool has_msr_star;
-static bool has_msr_hsave_pa;
-static bool has_msr_tsc_aux;
-static bool has_msr_tsc_adjust;
-static bool has_msr_tsc_deadline;
-static bool has_msr_feature_control;
-static bool has_msr_misc_enable;
-static bool has_msr_smbase;
-static bool has_msr_bndcfgs;
-static int lm_capable_kernel;
-static bool has_msr_hv_hypercall;
-static bool has_msr_hv_crash;
-static bool has_msr_hv_reset;
-static bool has_msr_hv_vpindex;
-static bool has_msr_hv_runtime;
-static bool has_msr_hv_synic;
-static bool has_msr_hv_stimer;
-static bool has_msr_xss;
-
-static bool has_msr_architectural_pmu;
-static uint32_t num_architectural_pmu_counters;
-
-static int has_xsave;
-static int has_xcrs;
-static int has_pit_state2;
-
-static bool has_msr_mcg_ext_ctl;
-
-static struct kvm_cpuid2 *cpuid_cache;
-
-int kvm_has_pit_state2(void)
-{
- return has_pit_state2;
-}
-
-bool kvm_has_smm(void)
-{
- return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
-}
-
-bool kvm_allows_irq0_override(void)
-{
- return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
-}
-
-static bool kvm_x2apic_api_set_flags(uint64_t flags)
-{
- KVMState *s = KVM_STATE(current_machine->accelerator);
-
- return !kvm_vm_enable_cap(s, KVM_CAP_X2APIC_API, 0, flags);
-}
-
-#define MEMORIZE(fn, _result) \
- ({ \
- static bool _memorized; \
- \
- if (_memorized) { \
- return _result; \
- } \
- _memorized = true; \
- _result = fn; \
- })
-
-static bool has_x2apic_api;
-
-bool kvm_has_x2apic_api(void)
-{
- return has_x2apic_api;
-}
-
-bool kvm_enable_x2apic(void)
-{
- return MEMORIZE(
- kvm_x2apic_api_set_flags(KVM_X2APIC_API_USE_32BIT_IDS |
- KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK),
- has_x2apic_api);
-}
-
-static int kvm_get_tsc(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- struct {
- struct kvm_msrs info;
- struct kvm_msr_entry entries[1];
- } msr_data;
- int ret;
-
- if (env->tsc_valid) {
- return 0;
- }
-
- msr_data.info.nmsrs = 1;
- msr_data.entries[0].index = MSR_IA32_TSC;
- env->tsc_valid = !runstate_is_running();
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
- if (ret < 0) {
- return ret;
- }
-
- assert(ret == 1);
- env->tsc = msr_data.entries[0].data;
- return 0;
-}
-
-static inline void do_kvm_synchronize_tsc(CPUState *cpu, run_on_cpu_data arg)
-{
- kvm_get_tsc(cpu);
-}
-
-void kvm_synchronize_all_tsc(void)
-{
- CPUState *cpu;
-
- if (kvm_enabled()) {
- CPU_FOREACH(cpu) {
- run_on_cpu(cpu, do_kvm_synchronize_tsc, RUN_ON_CPU_NULL);
- }
- }
-}
-
-static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
-{
- struct kvm_cpuid2 *cpuid;
- int r, size;
-
- size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
- cpuid = g_malloc0(size);
- cpuid->nent = max;
- r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
- if (r == 0 && cpuid->nent >= max) {
- r = -E2BIG;
- }
- if (r < 0) {
- if (r == -E2BIG) {
- g_free(cpuid);
- return NULL;
- } else {
- fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
- strerror(-r));
- exit(1);
- }
- }
- return cpuid;
-}
-
-/* Run KVM_GET_SUPPORTED_CPUID ioctl(), allocating a buffer large enough
- * for all entries.
- */
-static struct kvm_cpuid2 *get_supported_cpuid(KVMState *s)
-{
- struct kvm_cpuid2 *cpuid;
- int max = 1;
-
- if (cpuid_cache != NULL) {
- return cpuid_cache;
- }
- while ((cpuid = try_get_cpuid(s, max)) == NULL) {
- max *= 2;
- }
- cpuid_cache = cpuid;
- return cpuid;
-}
-
-static const struct kvm_para_features {
- int cap;
- int feature;
-} para_features[] = {
- { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
- { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
- { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
- { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
-};
-
-static int get_para_features(KVMState *s)
-{
- int i, features = 0;
-
- for (i = 0; i < ARRAY_SIZE(para_features); i++) {
- if (kvm_check_extension(s, para_features[i].cap)) {
- features |= (1 << para_features[i].feature);
- }
- }
-
- return features;
-}
-
-
-/* Returns the value for a specific register on the cpuid entry
- */
-static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg)
-{
- uint32_t ret = 0;
- switch (reg) {
- case R_EAX:
- ret = entry->eax;
- break;
- case R_EBX:
- ret = entry->ebx;
- break;
- case R_ECX:
- ret = entry->ecx;
- break;
- case R_EDX:
- ret = entry->edx;
- break;
- }
- return ret;
-}
-
-/* Find matching entry for function/index on kvm_cpuid2 struct
- */
-static struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid,
- uint32_t function,
- uint32_t index)
-{
- int i;
- for (i = 0; i < cpuid->nent; ++i) {
- if (cpuid->entries[i].function == function &&
- cpuid->entries[i].index == index) {
- return &cpuid->entries[i];
- }
- }
- /* not found: */
- return NULL;
-}
-
-uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
- uint32_t index, int reg)
-{
- struct kvm_cpuid2 *cpuid;
- uint32_t ret = 0;
- uint32_t cpuid_1_edx;
- bool found = false;
-
- cpuid = get_supported_cpuid(s);
-
- struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index);
- if (entry) {
- found = true;
- ret = cpuid_entry_get_reg(entry, reg);
- }
-
- /* Fixups for the data returned by KVM, below */
-
- if (function == 1 && reg == R_EDX) {
- /* KVM before 2.6.30 misreports the following features */
- ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA;
- } else if (function == 1 && reg == R_ECX) {
- /* We can set the hypervisor flag, even if KVM does not return it on
- * GET_SUPPORTED_CPUID
- */
- ret |= CPUID_EXT_HYPERVISOR;
- /* tsc-deadline flag is not returned by GET_SUPPORTED_CPUID, but it
- * can be enabled if the kernel has KVM_CAP_TSC_DEADLINE_TIMER,
- * and the irqchip is in the kernel.
- */
- if (kvm_irqchip_in_kernel() &&
- kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) {
- ret |= CPUID_EXT_TSC_DEADLINE_TIMER;
- }
-
- /* x2apic is reported by GET_SUPPORTED_CPUID, but it can't be enabled
- * without the in-kernel irqchip
- */
- if (!kvm_irqchip_in_kernel()) {
- ret &= ~CPUID_EXT_X2APIC;
- }
- } else if (function == 6 && reg == R_EAX) {
- ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */
- } else if (function == 0x80000001 && reg == R_EDX) {
- /* On Intel, kvm returns cpuid according to the Intel spec,
- * so add missing bits according to the AMD spec:
- */
- cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
- ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES;
- } else if (function == KVM_CPUID_FEATURES && reg == R_EAX) {
- /* kvm_pv_unhalt is reported by GET_SUPPORTED_CPUID, but it can't
- * be enabled without the in-kernel irqchip
- */
- if (!kvm_irqchip_in_kernel()) {
- ret &= ~(1U << KVM_FEATURE_PV_UNHALT);
- }
- }
-
- /* fallback for older kernels */
- if ((function == KVM_CPUID_FEATURES) && !found) {
- ret = get_para_features(s);
- }
-
- return ret;
-}
-
-typedef struct HWPoisonPage {
- ram_addr_t ram_addr;
- QLIST_ENTRY(HWPoisonPage) list;
-} HWPoisonPage;
-
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
- QLIST_HEAD_INITIALIZER(hwpoison_page_list);
-
-static void kvm_unpoison_all(void *param)
-{
- HWPoisonPage *page, *next_page;
-
- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
- QLIST_REMOVE(page, list);
- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
- g_free(page);
- }
-}
-
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
-{
- HWPoisonPage *page;
-
- QLIST_FOREACH(page, &hwpoison_page_list, list) {
- if (page->ram_addr == ram_addr) {
- return;
- }
- }
- page = g_new(HWPoisonPage, 1);
- page->ram_addr = ram_addr;
- QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
-}
-
-static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
- int *max_banks)
-{
- int r;
-
- r = kvm_check_extension(s, KVM_CAP_MCE);
- if (r > 0) {
- *max_banks = r;
- return kvm_ioctl(s, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap);
- }
- return -ENOSYS;
-}
-
-static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
- MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S;
- uint64_t mcg_status = MCG_STATUS_MCIP;
- int flags = 0;
-
- if (code == BUS_MCEERR_AR) {
- status |= MCI_STATUS_AR | 0x134;
- mcg_status |= MCG_STATUS_EIPV;
- } else {
- status |= 0xc0;
- mcg_status |= MCG_STATUS_RIPV;
- }
-
- flags = cpu_x86_support_mca_broadcast(env) ? MCE_INJECT_BROADCAST : 0;
- /* We need to read back the value of MSR_EXT_MCG_CTL that was set by the
- * guest kernel back into env->mcg_ext_ctl.
- */
- cpu_synchronize_state(cs);
- if (env->mcg_ext_ctl & MCG_EXT_CTL_LMCE_EN) {
- mcg_status |= MCG_STATUS_LMCE;
- flags = 0;
- }
-
- cpu_x86_inject_mce(NULL, cpu, 9, status, mcg_status, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, flags);
-}
-
-static void hardware_memory_error(void)
-{
- fprintf(stderr, "Hardware memory error!\n");
- exit(1);
-}
-
-int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
-{
- X86CPU *cpu = X86_CPU(c);
- CPUX86State *env = &cpu->env;
- ram_addr_t ram_addr;
- hwaddr paddr;
-
- if ((env->mcg_cap & MCG_SER_P) && addr
- && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
- ram_addr = qemu_ram_addr_from_host(addr);
- if (ram_addr == RAM_ADDR_INVALID ||
- !kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
- fprintf(stderr, "Hardware memory error for memory used by "
- "QEMU itself instead of guest system!\n");
- /* Hope we are lucky for AO MCE */
- if (code == BUS_MCEERR_AO) {
- return 0;
- } else {
- hardware_memory_error();
- }
- }
- kvm_hwpoison_page_add(ram_addr);
- kvm_mce_inject(cpu, paddr, code);
- } else {
- if (code == BUS_MCEERR_AO) {
- return 0;
- } else if (code == BUS_MCEERR_AR) {
- hardware_memory_error();
- } else {
- return 1;
- }
- }
- return 0;
-}
-
-int kvm_arch_on_sigbus(int code, void *addr)
-{
- X86CPU *cpu = X86_CPU(first_cpu);
-
- if ((cpu->env.mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
- ram_addr_t ram_addr;
- hwaddr paddr;
-
- /* Hope we are lucky for AO MCE */
- ram_addr = qemu_ram_addr_from_host(addr);
- if (ram_addr == RAM_ADDR_INVALID ||
- !kvm_physical_memory_addr_from_host(first_cpu->kvm_state,
- addr, &paddr)) {
- fprintf(stderr, "Hardware memory error for memory used by "
- "QEMU itself instead of guest system!: %p\n", addr);
- return 0;
- }
- kvm_hwpoison_page_add(ram_addr);
- kvm_mce_inject(X86_CPU(first_cpu), paddr, code);
- } else {
- if (code == BUS_MCEERR_AO) {
- return 0;
- } else if (code == BUS_MCEERR_AR) {
- hardware_memory_error();
- } else {
- return 1;
- }
- }
- return 0;
-}
-
-static int kvm_inject_mce_oldstyle(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
-
- if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
- unsigned int bank, bank_num = env->mcg_cap & 0xff;
- struct kvm_x86_mce mce;
-
- env->exception_injected = -1;
-
- /*
- * There must be at least one bank in use if an MCE is pending.
- * Find it and use its values for the event injection.
- */
- for (bank = 0; bank < bank_num; bank++) {
- if (env->mce_banks[bank * 4 + 1] & MCI_STATUS_VAL) {
- break;
- }
- }
- assert(bank < bank_num);
-
- mce.bank = bank;
- mce.status = env->mce_banks[bank * 4 + 1];
- mce.mcg_status = env->mcg_status;
- mce.addr = env->mce_banks[bank * 4 + 2];
- mce.misc = env->mce_banks[bank * 4 + 3];
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_X86_SET_MCE, &mce);
- }
- return 0;
-}
-
-static void cpu_update_state(void *opaque, int running, RunState state)
-{
- CPUX86State *env = opaque;
-
- if (running) {
- env->tsc_valid = false;
- }
-}
-
-unsigned long kvm_arch_vcpu_id(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- return cpu->apic_id;
-}
-
-#ifndef KVM_CPUID_SIGNATURE_NEXT
-#define KVM_CPUID_SIGNATURE_NEXT 0x40000100
-#endif
-
-static bool hyperv_hypercall_available(X86CPU *cpu)
-{
- return cpu->hyperv_vapic ||
- (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY);
-}
-
-static bool hyperv_enabled(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- return kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV) > 0 &&
- (hyperv_hypercall_available(cpu) ||
- cpu->hyperv_time ||
- cpu->hyperv_relaxed_timing ||
- cpu->hyperv_crash ||
- cpu->hyperv_reset ||
- cpu->hyperv_vpindex ||
- cpu->hyperv_runtime ||
- cpu->hyperv_synic ||
- cpu->hyperv_stimer);
-}
-
-static int kvm_arch_set_tsc_khz(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- int r;
-
- if (!env->tsc_khz) {
- return 0;
- }
-
- r = kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL) ?
- kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz) :
- -ENOTSUP;
- if (r < 0) {
- /* When KVM_SET_TSC_KHZ fails, it's an error only if the current
- * TSC frequency doesn't match the one we want.
- */
- int cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
- kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
- -ENOTSUP;
- if (cur_freq <= 0 || cur_freq != env->tsc_khz) {
- error_report("warning: TSC frequency mismatch between "
- "VM (%" PRId64 " kHz) and host (%d kHz), "
- "and TSC scaling unavailable",
- env->tsc_khz, cur_freq);
- return r;
- }
- }
-
- return 0;
-}
-
-static int hyperv_handle_properties(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- if (cpu->hyperv_time &&
- kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) <= 0) {
- cpu->hyperv_time = false;
- }
-
- if (cpu->hyperv_relaxed_timing) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
- }
- if (cpu->hyperv_vapic) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
- }
- if (cpu->hyperv_time) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
- env->features[FEAT_HYPERV_EAX] |= 0x200;
- }
- if (cpu->hyperv_crash && has_msr_hv_crash) {
- env->features[FEAT_HYPERV_EDX] |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
- }
- env->features[FEAT_HYPERV_EDX] |= HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
- if (cpu->hyperv_reset && has_msr_hv_reset) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_RESET_AVAILABLE;
- }
- if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_INDEX_AVAILABLE;
- }
- if (cpu->hyperv_runtime && has_msr_hv_runtime) {
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
- }
- if (cpu->hyperv_synic) {
- int sint;
-
- if (!has_msr_hv_synic ||
- kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
- fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
- return -ENOSYS;
- }
-
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNIC_AVAILABLE;
- env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
- for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
- env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
- }
- }
- if (cpu->hyperv_stimer) {
- if (!has_msr_hv_stimer) {
- fprintf(stderr, "Hyper-V timers aren't supported by kernel\n");
- return -ENOSYS;
- }
- env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNTIMER_AVAILABLE;
- }
- return 0;
-}
-
-static Error *invtsc_mig_blocker;
-
-#define KVM_MAX_CPUID_ENTRIES 100
-
-int kvm_arch_init_vcpu(CPUState *cs)
-{
- struct {
- struct kvm_cpuid2 cpuid;
- struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
- } QEMU_PACKED cpuid_data;
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- uint32_t limit, i, j, cpuid_i;
- uint32_t unused;
- struct kvm_cpuid_entry2 *c;
- uint32_t signature[3];
- int kvm_base = KVM_CPUID_SIGNATURE;
- int r;
-
- memset(&cpuid_data, 0, sizeof(cpuid_data));
-
- cpuid_i = 0;
-
- /* Paravirtualization CPUIDs */
- if (hyperv_enabled(cpu)) {
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
- if (!cpu->hyperv_vendor_id) {
- memcpy(signature, "Microsoft Hv", 12);
- } else {
- size_t len = strlen(cpu->hyperv_vendor_id);
-
- if (len > 12) {
- error_report("hv-vendor-id truncated to 12 characters");
- len = 12;
- }
- memset(signature, 0, 12);
- memcpy(signature, cpu->hyperv_vendor_id, len);
- }
- c->eax = HYPERV_CPUID_MIN;
- c->ebx = signature[0];
- c->ecx = signature[1];
- c->edx = signature[2];
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_INTERFACE;
- memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
- c->eax = signature[0];
- c->ebx = 0;
- c->ecx = 0;
- c->edx = 0;
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_VERSION;
- c->eax = 0x00001bbc;
- c->ebx = 0x00060001;
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_FEATURES;
- r = hyperv_handle_properties(cs);
- if (r) {
- return r;
- }
- c->eax = env->features[FEAT_HYPERV_EAX];
- c->ebx = env->features[FEAT_HYPERV_EBX];
- c->edx = env->features[FEAT_HYPERV_EDX];
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
- if (cpu->hyperv_relaxed_timing) {
- c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
- }
- if (cpu->hyperv_vapic) {
- c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
- }
- c->ebx = cpu->hyperv_spinlock_attempts;
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
- c->eax = 0x40;
- c->ebx = 0x40;
-
- kvm_base = KVM_CPUID_SIGNATURE_NEXT;
- has_msr_hv_hypercall = true;
- }
-
- if (cpu->expose_kvm) {
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_SIGNATURE | kvm_base;
- c->eax = KVM_CPUID_FEATURES | kvm_base;
- c->ebx = signature[0];
- c->ecx = signature[1];
- c->edx = signature[2];
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_FEATURES | kvm_base;
- c->eax = env->features[FEAT_KVM];
- }
-
- cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
-
- for (i = 0; i <= limit; i++) {
- if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
- fprintf(stderr, "unsupported level value: 0x%x\n", limit);
- abort();
- }
- c = &cpuid_data.entries[cpuid_i++];
-
- switch (i) {
- case 2: {
- /* Keep reading function 2 till all the input is received */
- int times;
-
- c->function = i;
- c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC |
- KVM_CPUID_FLAG_STATE_READ_NEXT;
- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
- times = c->eax & 0xff;
-
- for (j = 1; j < times; ++j) {
- if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
- fprintf(stderr, "cpuid_data is full, no space for "
- "cpuid(eax:2):eax & 0xf = 0x%x\n", times);
- abort();
- }
- c = &cpuid_data.entries[cpuid_i++];
- c->function = i;
- c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
- }
- break;
- }
- case 4:
- case 0xb:
- case 0xd:
- for (j = 0; ; j++) {
- if (i == 0xd && j == 64) {
- break;
- }
- c->function = i;
- c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
- c->index = j;
- cpu_x86_cpuid(env, i, j, &c->eax, &c->ebx, &c->ecx, &c->edx);
-
- if (i == 4 && c->eax == 0) {
- break;
- }
- if (i == 0xb && !(c->ecx & 0xff00)) {
- break;
- }
- if (i == 0xd && c->eax == 0) {
- continue;
- }
- if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
- fprintf(stderr, "cpuid_data is full, no space for "
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
- abort();
- }
- c = &cpuid_data.entries[cpuid_i++];
- }
- break;
- default:
- c->function = i;
- c->flags = 0;
- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
- break;
- }
- }
-
- if (limit >= 0x0a) {
- uint32_t ver;
-
- cpu_x86_cpuid(env, 0x0a, 0, &ver, &unused, &unused, &unused);
- if ((ver & 0xff) > 0) {
- has_msr_architectural_pmu = true;
- num_architectural_pmu_counters = (ver & 0xff00) >> 8;
-
- /* Shouldn't be more than 32, since that's the number of bits
- * available in EBX to tell us _which_ counters are available.
- * Play it safe.
- */
- if (num_architectural_pmu_counters > MAX_GP_COUNTERS) {
- num_architectural_pmu_counters = MAX_GP_COUNTERS;
- }
- }
- }
-
- cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
-
- for (i = 0x80000000; i <= limit; i++) {
- if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
- fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit);
- abort();
- }
- c = &cpuid_data.entries[cpuid_i++];
-
- c->function = i;
- c->flags = 0;
- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
- }
-
- /* Call Centaur's CPUID instructions they are supported. */
- if (env->cpuid_xlevel2 > 0) {
- cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused);
-
- for (i = 0xC0000000; i <= limit; i++) {
- if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
- fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit);
- abort();
- }
- c = &cpuid_data.entries[cpuid_i++];
-
- c->function = i;
- c->flags = 0;
- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
- }
- }
-
- cpuid_data.cpuid.nent = cpuid_i;
-
- if (((env->cpuid_version >> 8)&0xF) >= 6
- && (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
- (CPUID_MCE | CPUID_MCA)
- && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) {
- uint64_t mcg_cap, unsupported_caps;
- int banks;
- int ret;
-
- ret = kvm_get_mce_cap_supported(cs->kvm_state, &mcg_cap, &banks);
- if (ret < 0) {
- fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret));
- return ret;
- }
-
- if (banks < (env->mcg_cap & MCG_CAP_BANKS_MASK)) {
- error_report("kvm: Unsupported MCE bank count (QEMU = %d, KVM = %d)",
- (int)(env->mcg_cap & MCG_CAP_BANKS_MASK), banks);
- return -ENOTSUP;
- }
-
- unsupported_caps = env->mcg_cap & ~(mcg_cap | MCG_CAP_BANKS_MASK);
- if (unsupported_caps) {
- if (unsupported_caps & MCG_LMCE_P) {
- error_report("kvm: LMCE not supported");
- return -ENOTSUP;
- }
- error_report("warning: Unsupported MCG_CAP bits: 0x%" PRIx64,
- unsupported_caps);
- }
-
- env->mcg_cap &= mcg_cap | MCG_CAP_BANKS_MASK;
- ret = kvm_vcpu_ioctl(cs, KVM_X86_SETUP_MCE, &env->mcg_cap);
- if (ret < 0) {
- fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
- return ret;
- }
- }
-
- qemu_add_vm_change_state_handler(cpu_update_state, env);
-
- c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0);
- if (c) {
- has_msr_feature_control = !!(c->ecx & CPUID_EXT_VMX) ||
- !!(c->ecx & CPUID_EXT_SMX);
- }
-
- if (env->mcg_cap & MCG_LMCE_P) {
- has_msr_mcg_ext_ctl = has_msr_feature_control = true;
- }
-
- c = cpuid_find_entry(&cpuid_data.cpuid, 0x80000007, 0);
- if (c && (c->edx & 1<<8) && invtsc_mig_blocker == NULL) {
- /* for migration */
- error_setg(&invtsc_mig_blocker,
- "State blocked by non-migratable CPU device"
- " (invtsc flag)");
- migrate_add_blocker(invtsc_mig_blocker);
- /* for savevm */
- vmstate_x86_cpu.unmigratable = 1;
- }
-
- cpuid_data.cpuid.padding = 0;
- r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
- if (r) {
- return r;
- }
-
- r = kvm_arch_set_tsc_khz(cs);
- if (r < 0) {
- return r;
- }
-
- /* vcpu's TSC frequency is either specified by user, or following
- * the value used by KVM if the former is not present. In the
- * latter case, we query it from KVM and record in env->tsc_khz,
- * so that vcpu's TSC frequency can be migrated later via this field.
- */
- if (!env->tsc_khz) {
- r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
- kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
- -ENOTSUP;
- if (r > 0) {
- env->tsc_khz = r;
- }
- }
-
- if (has_xsave) {
- env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
- }
- cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE);
-
- if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP)) {
- has_msr_tsc_aux = false;
- }
-
- return 0;
-}
-
-void kvm_arch_reset_vcpu(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
-
- env->exception_injected = -1;
- env->interrupt_injected = -1;
- env->xcr0 = 1;
- if (kvm_irqchip_in_kernel()) {
- env->mp_state = cpu_is_bsp(cpu) ? KVM_MP_STATE_RUNNABLE :
- KVM_MP_STATE_UNINITIALIZED;
- } else {
- env->mp_state = KVM_MP_STATE_RUNNABLE;
- }
-}
-
-void kvm_arch_do_init_vcpu(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
-
- /* APs get directly into wait-for-SIPI state. */
- if (env->mp_state == KVM_MP_STATE_UNINITIALIZED) {
- env->mp_state = KVM_MP_STATE_INIT_RECEIVED;
- }
-}
-
-static int kvm_get_supported_msrs(KVMState *s)
-{
- static int kvm_supported_msrs;
- int ret = 0;
-
- /* first time */
- if (kvm_supported_msrs == 0) {
- struct kvm_msr_list msr_list, *kvm_msr_list;
-
- kvm_supported_msrs = -1;
-
- /* Obtain MSR list from KVM. These are the MSRs that we must
- * save/restore */
- msr_list.nmsrs = 0;
- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list);
- if (ret < 0 && ret != -E2BIG) {
- return ret;
- }
- /* Old kernel modules had a bug and could write beyond the provided
- memory. Allocate at least a safe amount of 1K. */
- kvm_msr_list = g_malloc0(MAX(1024, sizeof(msr_list) +
- msr_list.nmsrs *
- sizeof(msr_list.indices[0])));
-
- kvm_msr_list->nmsrs = msr_list.nmsrs;
- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
- if (ret >= 0) {
- int i;
-
- for (i = 0; i < kvm_msr_list->nmsrs; i++) {
- if (kvm_msr_list->indices[i] == MSR_STAR) {
- has_msr_star = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) {
- has_msr_hsave_pa = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_TSC_AUX) {
- has_msr_tsc_aux = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) {
- has_msr_tsc_adjust = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_IA32_TSCDEADLINE) {
- has_msr_tsc_deadline = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_IA32_SMBASE) {
- has_msr_smbase = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_IA32_MISC_ENABLE) {
- has_msr_misc_enable = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_IA32_BNDCFGS) {
- has_msr_bndcfgs = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == MSR_IA32_XSS) {
- has_msr_xss = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_CRASH_CTL) {
- has_msr_hv_crash = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_RESET) {
- has_msr_hv_reset = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_INDEX) {
- has_msr_hv_vpindex = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_RUNTIME) {
- has_msr_hv_runtime = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
- has_msr_hv_synic = true;
- continue;
- }
- if (kvm_msr_list->indices[i] == HV_X64_MSR_STIMER0_CONFIG) {
- has_msr_hv_stimer = true;
- continue;
- }
- }
- }
-
- g_free(kvm_msr_list);
- }
-
- return ret;
-}
-
-static Notifier smram_machine_done;
-static KVMMemoryListener smram_listener;
-static AddressSpace smram_address_space;
-static MemoryRegion smram_as_root;
-static MemoryRegion smram_as_mem;
-
-static void register_smram_listener(Notifier *n, void *unused)
-{
- MemoryRegion *smram =
- (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
-
- /* Outer container... */
- memory_region_init(&smram_as_root, OBJECT(kvm_state), "mem-container-smram", ~0ull);
- memory_region_set_enabled(&smram_as_root, true);
-
- /* ... with two regions inside: normal system memory with low
- * priority, and...
- */
- memory_region_init_alias(&smram_as_mem, OBJECT(kvm_state), "mem-smram",
- get_system_memory(), 0, ~0ull);
- memory_region_add_subregion_overlap(&smram_as_root, 0, &smram_as_mem, 0);
- memory_region_set_enabled(&smram_as_mem, true);
-
- if (smram) {
- /* ... SMRAM with higher priority */
- memory_region_add_subregion_overlap(&smram_as_root, 0, smram, 10);
- memory_region_set_enabled(smram, true);
- }
-
- address_space_init(&smram_address_space, &smram_as_root, "KVM-SMRAM");
- kvm_memory_listener_register(kvm_state, &smram_listener,
- &smram_address_space, 1);
-}
-
-int kvm_arch_init(MachineState *ms, KVMState *s)
-{
- uint64_t identity_base = 0xfffbc000;
- uint64_t shadow_mem;
- int ret;
- struct utsname utsname;
-
-#ifdef KVM_CAP_XSAVE
- has_xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
-#endif
-
-#ifdef KVM_CAP_XCRS
- has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
-#endif
-
-#ifdef KVM_CAP_PIT_STATE2
- has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
-#endif
-
- ret = kvm_get_supported_msrs(s);
- if (ret < 0) {
- return ret;
- }
-
- uname(&utsname);
- lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
-
- /*
- * On older Intel CPUs, KVM uses vm86 mode to emulate 16-bit code directly.
- * In order to use vm86 mode, an EPT identity map and a TSS are needed.
- * Since these must be part of guest physical memory, we need to allocate
- * them, both by setting their start addresses in the kernel and by
- * creating a corresponding e820 entry. We need 4 pages before the BIOS.
- *
- * Older KVM versions may not support setting the identity map base. In
- * that case we need to stick with the default, i.e. a 256K maximum BIOS
- * size.
- */
- if (kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
- /* Allows up to 16M BIOSes. */
- identity_base = 0xfeffc000;
-
- ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &identity_base);
- if (ret < 0) {
- return ret;
- }
- }
-
- /* Set TSS base one page after EPT identity map. */
- ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, identity_base + 0x1000);
- if (ret < 0) {
- return ret;
- }
-
- /* Tell fw_cfg to notify the BIOS to reserve the range. */
- ret = e820_add_entry(identity_base, 0x4000, E820_RESERVED);
- if (ret < 0) {
- fprintf(stderr, "e820_add_entry() table is full\n");
- return ret;
- }
- qemu_register_reset(kvm_unpoison_all, NULL);
-
- shadow_mem = machine_kvm_shadow_mem(ms);
- if (shadow_mem != -1) {
- shadow_mem /= 4096;
- ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
- if (ret < 0) {
- return ret;
- }
- }
-
- if (kvm_check_extension(s, KVM_CAP_X86_SMM)) {
- smram_machine_done.notify = register_smram_listener;
- qemu_add_machine_init_done_notifier(&smram_machine_done);
- }
- return 0;
-}
-
-static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
-{
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- lhs->type = 3;
- lhs->present = 1;
- lhs->dpl = 3;
- lhs->db = 0;
- lhs->s = 1;
- lhs->l = 0;
- lhs->g = 0;
- lhs->avl = 0;
- lhs->unusable = 0;
-}
-
-static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
-{
- unsigned flags = rhs->flags;
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- lhs->type = (flags >> DESC_TYPE_SHIFT) & 15;
- lhs->present = (flags & DESC_P_MASK) != 0;
- lhs->dpl = (flags >> DESC_DPL_SHIFT) & 3;
- lhs->db = (flags >> DESC_B_SHIFT) & 1;
- lhs->s = (flags & DESC_S_MASK) != 0;
- lhs->l = (flags >> DESC_L_SHIFT) & 1;
- lhs->g = (flags & DESC_G_MASK) != 0;
- lhs->avl = (flags & DESC_AVL_MASK) != 0;
- lhs->unusable = !lhs->present;
- lhs->padding = 0;
-}
-
-static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
-{
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- if (rhs->unusable) {
- lhs->flags = 0;
- } else {
- lhs->flags = (rhs->type << DESC_TYPE_SHIFT) |
- (rhs->present * DESC_P_MASK) |
- (rhs->dpl << DESC_DPL_SHIFT) |
- (rhs->db << DESC_B_SHIFT) |
- (rhs->s * DESC_S_MASK) |
- (rhs->l << DESC_L_SHIFT) |
- (rhs->g * DESC_G_MASK) |
- (rhs->avl * DESC_AVL_MASK);
- }
-}
-
-static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
-{
- if (set) {
- *kvm_reg = *qemu_reg;
- } else {
- *qemu_reg = *kvm_reg;
- }
-}
-
-static int kvm_getput_regs(X86CPU *cpu, int set)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_regs regs;
- int ret = 0;
-
- if (!set) {
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_REGS, &regs);
- if (ret < 0) {
- return ret;
- }
- }
-
- kvm_getput_reg(&regs.rax, &env->regs[R_EAX], set);
- kvm_getput_reg(&regs.rbx, &env->regs[R_EBX], set);
- kvm_getput_reg(&regs.rcx, &env->regs[R_ECX], set);
- kvm_getput_reg(&regs.rdx, &env->regs[R_EDX], set);
- kvm_getput_reg(&regs.rsi, &env->regs[R_ESI], set);
- kvm_getput_reg(&regs.rdi, &env->regs[R_EDI], set);
- kvm_getput_reg(&regs.rsp, &env->regs[R_ESP], set);
- kvm_getput_reg(&regs.rbp, &env->regs[R_EBP], set);
-#ifdef TARGET_X86_64
- kvm_getput_reg(&regs.r8, &env->regs[8], set);
- kvm_getput_reg(&regs.r9, &env->regs[9], set);
- kvm_getput_reg(&regs.r10, &env->regs[10], set);
- kvm_getput_reg(&regs.r11, &env->regs[11], set);
- kvm_getput_reg(&regs.r12, &env->regs[12], set);
- kvm_getput_reg(&regs.r13, &env->regs[13], set);
- kvm_getput_reg(&regs.r14, &env->regs[14], set);
- kvm_getput_reg(&regs.r15, &env->regs[15], set);
-#endif
-
- kvm_getput_reg(&regs.rflags, &env->eflags, set);
- kvm_getput_reg(&regs.rip, &env->eip, set);
-
- if (set) {
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_REGS, &regs);
- }
-
- return ret;
-}
-
-static int kvm_put_fpu(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_fpu fpu;
- int i;
-
- memset(&fpu, 0, sizeof fpu);
- fpu.fsw = env->fpus & ~(7 << 11);
- fpu.fsw |= (env->fpstt & 7) << 11;
- fpu.fcw = env->fpuc;
- fpu.last_opcode = env->fpop;
- fpu.last_ip = env->fpip;
- fpu.last_dp = env->fpdp;
- for (i = 0; i < 8; ++i) {
- fpu.ftwx |= (!env->fptags[i]) << i;
- }
- memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
- for (i = 0; i < CPU_NB_REGS; i++) {
- stq_p(&fpu.xmm[i][0], env->xmm_regs[i].ZMM_Q(0));
- stq_p(&fpu.xmm[i][8], env->xmm_regs[i].ZMM_Q(1));
- }
- fpu.mxcsr = env->mxcsr;
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu);
-}
-
-#define XSAVE_FCW_FSW 0
-#define XSAVE_FTW_FOP 1
-#define XSAVE_CWD_RIP 2
-#define XSAVE_CWD_RDP 4
-#define XSAVE_MXCSR 6
-#define XSAVE_ST_SPACE 8
-#define XSAVE_XMM_SPACE 40
-#define XSAVE_XSTATE_BV 128
-#define XSAVE_YMMH_SPACE 144
-#define XSAVE_BNDREGS 240
-#define XSAVE_BNDCSR 256
-#define XSAVE_OPMASK 272
-#define XSAVE_ZMM_Hi256 288
-#define XSAVE_Hi16_ZMM 416
-#define XSAVE_PKRU 672
-
-#define XSAVE_BYTE_OFFSET(word_offset) \
- ((word_offset) * sizeof(((struct kvm_xsave *)0)->region[0]))
-
-#define ASSERT_OFFSET(word_offset, field) \
- QEMU_BUILD_BUG_ON(XSAVE_BYTE_OFFSET(word_offset) != \
- offsetof(X86XSaveArea, field))
-
-ASSERT_OFFSET(XSAVE_FCW_FSW, legacy.fcw);
-ASSERT_OFFSET(XSAVE_FTW_FOP, legacy.ftw);
-ASSERT_OFFSET(XSAVE_CWD_RIP, legacy.fpip);
-ASSERT_OFFSET(XSAVE_CWD_RDP, legacy.fpdp);
-ASSERT_OFFSET(XSAVE_MXCSR, legacy.mxcsr);
-ASSERT_OFFSET(XSAVE_ST_SPACE, legacy.fpregs);
-ASSERT_OFFSET(XSAVE_XMM_SPACE, legacy.xmm_regs);
-ASSERT_OFFSET(XSAVE_XSTATE_BV, header.xstate_bv);
-ASSERT_OFFSET(XSAVE_YMMH_SPACE, avx_state);
-ASSERT_OFFSET(XSAVE_BNDREGS, bndreg_state);
-ASSERT_OFFSET(XSAVE_BNDCSR, bndcsr_state);
-ASSERT_OFFSET(XSAVE_OPMASK, opmask_state);
-ASSERT_OFFSET(XSAVE_ZMM_Hi256, zmm_hi256_state);
-ASSERT_OFFSET(XSAVE_Hi16_ZMM, hi16_zmm_state);
-ASSERT_OFFSET(XSAVE_PKRU, pkru_state);
-
-static int kvm_put_xsave(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- X86XSaveArea *xsave = env->kvm_xsave_buf;
- uint16_t cwd, swd, twd;
- int i;
-
- if (!has_xsave) {
- return kvm_put_fpu(cpu);
- }
-
- memset(xsave, 0, sizeof(struct kvm_xsave));
- twd = 0;
- swd = env->fpus & ~(7 << 11);
- swd |= (env->fpstt & 7) << 11;
- cwd = env->fpuc;
- for (i = 0; i < 8; ++i) {
- twd |= (!env->fptags[i]) << i;
- }
- xsave->legacy.fcw = cwd;
- xsave->legacy.fsw = swd;
- xsave->legacy.ftw = twd;
- xsave->legacy.fpop = env->fpop;
- xsave->legacy.fpip = env->fpip;
- xsave->legacy.fpdp = env->fpdp;
- memcpy(&xsave->legacy.fpregs, env->fpregs,
- sizeof env->fpregs);
- xsave->legacy.mxcsr = env->mxcsr;
- xsave->header.xstate_bv = env->xstate_bv;
- memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs,
- sizeof env->bnd_regs);
- xsave->bndcsr_state.bndcsr = env->bndcs_regs;
- memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs,
- sizeof env->opmask_regs);
-
- for (i = 0; i < CPU_NB_REGS; i++) {
- uint8_t *xmm = xsave->legacy.xmm_regs[i];
- uint8_t *ymmh = xsave->avx_state.ymmh[i];
- uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
- stq_p(xmm, env->xmm_regs[i].ZMM_Q(0));
- stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1));
- stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2));
- stq_p(ymmh+8, env->xmm_regs[i].ZMM_Q(3));
- stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4));
- stq_p(zmmh+8, env->xmm_regs[i].ZMM_Q(5));
- stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6));
- stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7));
- }
-
-#ifdef TARGET_X86_64
- memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16],
- 16 * sizeof env->xmm_regs[16]);
- memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
-#endif
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
-}
-
-static int kvm_put_xcrs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_xcrs xcrs = {};
-
- if (!has_xcrs) {
- return 0;
- }
-
- xcrs.nr_xcrs = 1;
- xcrs.flags = 0;
- xcrs.xcrs[0].xcr = 0;
- xcrs.xcrs[0].value = env->xcr0;
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XCRS, &xcrs);
-}
-
-static int kvm_put_sregs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_sregs sregs;
-
- memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
- if (env->interrupt_injected >= 0) {
- sregs.interrupt_bitmap[env->interrupt_injected / 64] |=
- (uint64_t)1 << (env->interrupt_injected % 64);
- }
-
- if ((env->eflags & VM_MASK)) {
- set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
- set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
- set_v8086_seg(&sregs.es, &env->segs[R_ES]);
- set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
- set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
- set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
- } else {
- set_seg(&sregs.cs, &env->segs[R_CS]);
- set_seg(&sregs.ds, &env->segs[R_DS]);
- set_seg(&sregs.es, &env->segs[R_ES]);
- set_seg(&sregs.fs, &env->segs[R_FS]);
- set_seg(&sregs.gs, &env->segs[R_GS]);
- set_seg(&sregs.ss, &env->segs[R_SS]);
- }
-
- set_seg(&sregs.tr, &env->tr);
- set_seg(&sregs.ldt, &env->ldt);
-
- sregs.idt.limit = env->idt.limit;
- sregs.idt.base = env->idt.base;
- memset(sregs.idt.padding, 0, sizeof sregs.idt.padding);
- sregs.gdt.limit = env->gdt.limit;
- sregs.gdt.base = env->gdt.base;
- memset(sregs.gdt.padding, 0, sizeof sregs.gdt.padding);
-
- sregs.cr0 = env->cr[0];
- sregs.cr2 = env->cr[2];
- sregs.cr3 = env->cr[3];
- sregs.cr4 = env->cr[4];
-
- sregs.cr8 = cpu_get_apic_tpr(cpu->apic_state);
- sregs.apic_base = cpu_get_apic_base(cpu->apic_state);
-
- sregs.efer = env->efer;
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs);
-}
-
-static void kvm_msr_buf_reset(X86CPU *cpu)
-{
- memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE);
-}
-
-static void kvm_msr_entry_add(X86CPU *cpu, uint32_t index, uint64_t value)
-{
- struct kvm_msrs *msrs = cpu->kvm_msr_buf;
- void *limit = ((void *)msrs) + MSR_BUF_SIZE;
- struct kvm_msr_entry *entry = &msrs->entries[msrs->nmsrs];
-
- assert((void *)(entry + 1) <= limit);
-
- entry->index = index;
- entry->reserved = 0;
- entry->data = value;
- msrs->nmsrs++;
-}
-
-static int kvm_put_one_msr(X86CPU *cpu, int index, uint64_t value)
-{
- kvm_msr_buf_reset(cpu);
- kvm_msr_entry_add(cpu, index, value);
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
-}
-
-void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
-{
- int ret;
-
- ret = kvm_put_one_msr(cpu, MSR_IA32_APICBASE, value);
- assert(ret == 1);
-}
-
-static int kvm_put_tscdeadline_msr(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- int ret;
-
- if (!has_msr_tsc_deadline) {
- return 0;
- }
-
- ret = kvm_put_one_msr(cpu, MSR_IA32_TSCDEADLINE, env->tsc_deadline);
- if (ret < 0) {
- return ret;
- }
-
- assert(ret == 1);
- return 0;
-}
-
-/*
- * Provide a separate write service for the feature control MSR in order to
- * kick the VCPU out of VMXON or even guest mode on reset. This has to be done
- * before writing any other state because forcibly leaving nested mode
- * invalidates the VCPU state.
- */
-static int kvm_put_msr_feature_control(X86CPU *cpu)
-{
- int ret;
-
- if (!has_msr_feature_control) {
- return 0;
- }
-
- ret = kvm_put_one_msr(cpu, MSR_IA32_FEATURE_CONTROL,
- cpu->env.msr_ia32_feature_control);
- if (ret < 0) {
- return ret;
- }
-
- assert(ret == 1);
- return 0;
-}
-
-static int kvm_put_msrs(X86CPU *cpu, int level)
-{
- CPUX86State *env = &cpu->env;
- int i;
- int ret;
-
- kvm_msr_buf_reset(cpu);
-
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_CS, env->sysenter_cs);
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
- kvm_msr_entry_add(cpu, MSR_PAT, env->pat);
- if (has_msr_star) {
- kvm_msr_entry_add(cpu, MSR_STAR, env->star);
- }
- if (has_msr_hsave_pa) {
- kvm_msr_entry_add(cpu, MSR_VM_HSAVE_PA, env->vm_hsave);
- }
- if (has_msr_tsc_aux) {
- kvm_msr_entry_add(cpu, MSR_TSC_AUX, env->tsc_aux);
- }
- if (has_msr_tsc_adjust) {
- kvm_msr_entry_add(cpu, MSR_TSC_ADJUST, env->tsc_adjust);
- }
- if (has_msr_misc_enable) {
- kvm_msr_entry_add(cpu, MSR_IA32_MISC_ENABLE,
- env->msr_ia32_misc_enable);
- }
- if (has_msr_smbase) {
- kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, env->smbase);
- }
- if (has_msr_bndcfgs) {
- kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, env->msr_bndcfgs);
- }
- if (has_msr_xss) {
- kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss);
- }
-#ifdef TARGET_X86_64
- if (lm_capable_kernel) {
- kvm_msr_entry_add(cpu, MSR_CSTAR, env->cstar);
- kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase);
- kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask);
- kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
- }
-#endif
- /*
- * The following MSRs have side effects on the guest or are too heavy
- * for normal writeback. Limit them to reset or full state updates.
- */
- if (level >= KVM_PUT_RESET_STATE) {
- kvm_msr_entry_add(cpu, MSR_IA32_TSC, env->tsc);
- kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, env->system_time_msr);
- kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) {
- kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
- }
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) {
- kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, env->pv_eoi_en_msr);
- }
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) {
- kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, env->steal_time_msr);
- }
- if (has_msr_architectural_pmu) {
- /* Stop the counter. */
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0);
-
- /* Set the counter values. */
- for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i,
- env->msr_fixed_counters[i]);
- }
- for (i = 0; i < num_architectural_pmu_counters; i++) {
- kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i,
- env->msr_gp_counters[i]);
- kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i,
- env->msr_gp_evtsel[i]);
- }
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS,
- env->msr_global_status);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL,
- env->msr_global_ovf_ctrl);
-
- /* Now start the PMU. */
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL,
- env->msr_fixed_ctr_ctrl);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL,
- env->msr_global_ctrl);
- }
- if (has_msr_hv_hypercall) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID,
- env->msr_hv_guest_os_id);
- kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL,
- env->msr_hv_hypercall);
- }
- if (cpu->hyperv_vapic) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE,
- env->msr_hv_vapic);
- }
- if (cpu->hyperv_time) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc);
- }
- if (has_msr_hv_crash) {
- int j;
-
- for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++)
- kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j,
- env->msr_hv_crash_params[j]);
-
- kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_CTL,
- HV_X64_MSR_CRASH_CTL_NOTIFY);
- }
- if (has_msr_hv_runtime) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime);
- }
- if (cpu->hyperv_synic) {
- int j;
-
- kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL,
- env->msr_hv_synic_control);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION,
- env->msr_hv_synic_version);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP,
- env->msr_hv_synic_evt_page);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP,
- env->msr_hv_synic_msg_page);
-
- for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_SINT0 + j,
- env->msr_hv_synic_sint[j]);
- }
- }
- if (has_msr_hv_stimer) {
- int j;
-
- for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_config); j++) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_STIMER0_CONFIG + j * 2,
- env->msr_hv_stimer_config[j]);
- }
-
- for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_count); j++) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_STIMER0_COUNT + j * 2,
- env->msr_hv_stimer_count[j]);
- }
- }
- if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
- uint64_t phys_mask = MAKE_64BIT_MASK(0, cpu->phys_bits);
-
- kvm_msr_entry_add(cpu, MSR_MTRRdefType, env->mtrr_deftype);
- kvm_msr_entry_add(cpu, MSR_MTRRfix64K_00000, env->mtrr_fixed[0]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix16K_80000, env->mtrr_fixed[1]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]);
- for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
- /* The CPU GPs if we write to a bit above the physical limit of
- * the host CPU (and KVM emulates that)
- */
- uint64_t mask = env->mtrr_var[i].mask;
- mask &= phys_mask;
-
- kvm_msr_entry_add(cpu, MSR_MTRRphysBase(i),
- env->mtrr_var[i].base);
- kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), mask);
- }
- }
-
- /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
- * kvm_put_msr_feature_control. */
- }
- if (env->mcg_cap) {
- int i;
-
- kvm_msr_entry_add(cpu, MSR_MCG_STATUS, env->mcg_status);
- kvm_msr_entry_add(cpu, MSR_MCG_CTL, env->mcg_ctl);
- if (has_msr_mcg_ext_ctl) {
- kvm_msr_entry_add(cpu, MSR_MCG_EXT_CTL, env->mcg_ext_ctl);
- }
- for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
- kvm_msr_entry_add(cpu, MSR_MC0_CTL + i, env->mce_banks[i]);
- }
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
- if (ret < 0) {
- return ret;
- }
-
- assert(ret == cpu->kvm_msr_buf->nmsrs);
- return 0;
-}
-
-
-static int kvm_get_fpu(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_fpu fpu;
- int i, ret;
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_FPU, &fpu);
- if (ret < 0) {
- return ret;
- }
-
- env->fpstt = (fpu.fsw >> 11) & 7;
- env->fpus = fpu.fsw;
- env->fpuc = fpu.fcw;
- env->fpop = fpu.last_opcode;
- env->fpip = fpu.last_ip;
- env->fpdp = fpu.last_dp;
- for (i = 0; i < 8; ++i) {
- env->fptags[i] = !((fpu.ftwx >> i) & 1);
- }
- memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
- for (i = 0; i < CPU_NB_REGS; i++) {
- env->xmm_regs[i].ZMM_Q(0) = ldq_p(&fpu.xmm[i][0]);
- env->xmm_regs[i].ZMM_Q(1) = ldq_p(&fpu.xmm[i][8]);
- }
- env->mxcsr = fpu.mxcsr;
-
- return 0;
-}
-
-static int kvm_get_xsave(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- X86XSaveArea *xsave = env->kvm_xsave_buf;
- int ret, i;
- uint16_t cwd, swd, twd;
-
- if (!has_xsave) {
- return kvm_get_fpu(cpu);
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XSAVE, xsave);
- if (ret < 0) {
- return ret;
- }
-
- cwd = xsave->legacy.fcw;
- swd = xsave->legacy.fsw;
- twd = xsave->legacy.ftw;
- env->fpop = xsave->legacy.fpop;
- env->fpstt = (swd >> 11) & 7;
- env->fpus = swd;
- env->fpuc = cwd;
- for (i = 0; i < 8; ++i) {
- env->fptags[i] = !((twd >> i) & 1);
- }
- env->fpip = xsave->legacy.fpip;
- env->fpdp = xsave->legacy.fpdp;
- env->mxcsr = xsave->legacy.mxcsr;
- memcpy(env->fpregs, &xsave->legacy.fpregs,
- sizeof env->fpregs);
- env->xstate_bv = xsave->header.xstate_bv;
- memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs,
- sizeof env->bnd_regs);
- env->bndcs_regs = xsave->bndcsr_state.bndcsr;
- memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs,
- sizeof env->opmask_regs);
-
- for (i = 0; i < CPU_NB_REGS; i++) {
- uint8_t *xmm = xsave->legacy.xmm_regs[i];
- uint8_t *ymmh = xsave->avx_state.ymmh[i];
- uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
- env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm);
- env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8);
- env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh);
- env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8);
- env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh);
- env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8);
- env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16);
- env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24);
- }
-
-#ifdef TARGET_X86_64
- memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm,
- 16 * sizeof env->xmm_regs[16]);
- memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
-#endif
- return 0;
-}
-
-static int kvm_get_xcrs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- int i, ret;
- struct kvm_xcrs xcrs;
-
- if (!has_xcrs) {
- return 0;
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XCRS, &xcrs);
- if (ret < 0) {
- return ret;
- }
-
- for (i = 0; i < xcrs.nr_xcrs; i++) {
- /* Only support xcr0 now */
- if (xcrs.xcrs[i].xcr == 0) {
- env->xcr0 = xcrs.xcrs[i].value;
- break;
- }
- }
- return 0;
-}
-
-static int kvm_get_sregs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_sregs sregs;
- uint32_t hflags;
- int bit, i, ret;
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs);
- if (ret < 0) {
- return ret;
- }
-
- /* There can only be one pending IRQ set in the bitmap at a time, so try
- to find it and save its number instead (-1 for none). */
- env->interrupt_injected = -1;
- for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) {
- if (sregs.interrupt_bitmap[i]) {
- bit = ctz64(sregs.interrupt_bitmap[i]);
- env->interrupt_injected = i * 64 + bit;
- break;
- }
- }
-
- get_seg(&env->segs[R_CS], &sregs.cs);
- get_seg(&env->segs[R_DS], &sregs.ds);
- get_seg(&env->segs[R_ES], &sregs.es);
- get_seg(&env->segs[R_FS], &sregs.fs);
- get_seg(&env->segs[R_GS], &sregs.gs);
- get_seg(&env->segs[R_SS], &sregs.ss);
-
- get_seg(&env->tr, &sregs.tr);
- get_seg(&env->ldt, &sregs.ldt);
-
- env->idt.limit = sregs.idt.limit;
- env->idt.base = sregs.idt.base;
- env->gdt.limit = sregs.gdt.limit;
- env->gdt.base = sregs.gdt.base;
-
- env->cr[0] = sregs.cr0;
- env->cr[2] = sregs.cr2;
- env->cr[3] = sregs.cr3;
- env->cr[4] = sregs.cr4;
-
- env->efer = sregs.efer;
-
- /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */
-
-#define HFLAG_COPY_MASK \
- ~( HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
- HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
- HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
- HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
-
- hflags = env->hflags & HFLAG_COPY_MASK;
- hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
- hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
- hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
- (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
- hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
-
- if (env->cr[4] & CR4_OSFXSR_MASK) {
- hflags |= HF_OSFXSR_MASK;
- }
-
- if (env->efer & MSR_EFER_LMA) {
- hflags |= HF_LMA_MASK;
- }
-
- if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
- hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
- } else {
- hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_CS32_SHIFT);
- hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_SS32_SHIFT);
- if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK) ||
- !(hflags & HF_CS32_MASK)) {
- hflags |= HF_ADDSEG_MASK;
- } else {
- hflags |= ((env->segs[R_DS].base | env->segs[R_ES].base |
- env->segs[R_SS].base) != 0) << HF_ADDSEG_SHIFT;
- }
- }
- env->hflags = hflags;
-
- return 0;
-}
-
-static int kvm_get_msrs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_msr_entry *msrs = cpu->kvm_msr_buf->entries;
- int ret, i;
- uint64_t mtrr_top_bits;
-
- kvm_msr_buf_reset(cpu);
-
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_CS, 0);
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_ESP, 0);
- kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_EIP, 0);
- kvm_msr_entry_add(cpu, MSR_PAT, 0);
- if (has_msr_star) {
- kvm_msr_entry_add(cpu, MSR_STAR, 0);
- }
- if (has_msr_hsave_pa) {
- kvm_msr_entry_add(cpu, MSR_VM_HSAVE_PA, 0);
- }
- if (has_msr_tsc_aux) {
- kvm_msr_entry_add(cpu, MSR_TSC_AUX, 0);
- }
- if (has_msr_tsc_adjust) {
- kvm_msr_entry_add(cpu, MSR_TSC_ADJUST, 0);
- }
- if (has_msr_tsc_deadline) {
- kvm_msr_entry_add(cpu, MSR_IA32_TSCDEADLINE, 0);
- }
- if (has_msr_misc_enable) {
- kvm_msr_entry_add(cpu, MSR_IA32_MISC_ENABLE, 0);
- }
- if (has_msr_smbase) {
- kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, 0);
- }
- if (has_msr_feature_control) {
- kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL, 0);
- }
- if (has_msr_bndcfgs) {
- kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, 0);
- }
- if (has_msr_xss) {
- kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0);
- }
-
-
- if (!env->tsc_valid) {
- kvm_msr_entry_add(cpu, MSR_IA32_TSC, 0);
- env->tsc_valid = !runstate_is_running();
- }
-
-#ifdef TARGET_X86_64
- if (lm_capable_kernel) {
- kvm_msr_entry_add(cpu, MSR_CSTAR, 0);
- kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0);
- kvm_msr_entry_add(cpu, MSR_FMASK, 0);
- kvm_msr_entry_add(cpu, MSR_LSTAR, 0);
- }
-#endif
- kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0);
- kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, 0);
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) {
- kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0);
- }
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) {
- kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, 0);
- }
- if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) {
- kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, 0);
- }
- if (has_msr_architectural_pmu) {
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, 0);
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, 0);
- for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
- kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, 0);
- }
- for (i = 0; i < num_architectural_pmu_counters; i++) {
- kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, 0);
- kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, 0);
- }
- }
-
- if (env->mcg_cap) {
- kvm_msr_entry_add(cpu, MSR_MCG_STATUS, 0);
- kvm_msr_entry_add(cpu, MSR_MCG_CTL, 0);
- if (has_msr_mcg_ext_ctl) {
- kvm_msr_entry_add(cpu, MSR_MCG_EXT_CTL, 0);
- }
- for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
- kvm_msr_entry_add(cpu, MSR_MC0_CTL + i, 0);
- }
- }
-
- if (has_msr_hv_hypercall) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL, 0);
- kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID, 0);
- }
- if (cpu->hyperv_vapic) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE, 0);
- }
- if (cpu->hyperv_time) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, 0);
- }
- if (has_msr_hv_crash) {
- int j;
-
- for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j, 0);
- }
- }
- if (has_msr_hv_runtime) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, 0);
- }
- if (cpu->hyperv_synic) {
- uint32_t msr;
-
- kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL, 0);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION, 0);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP, 0);
- kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP, 0);
- for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
- kvm_msr_entry_add(cpu, msr, 0);
- }
- }
- if (has_msr_hv_stimer) {
- uint32_t msr;
-
- for (msr = HV_X64_MSR_STIMER0_CONFIG; msr <= HV_X64_MSR_STIMER3_COUNT;
- msr++) {
- kvm_msr_entry_add(cpu, msr, 0);
- }
- }
- if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
- kvm_msr_entry_add(cpu, MSR_MTRRdefType, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix64K_00000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix16K_80000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix16K_A0000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C0000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C8000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D0000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D8000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E0000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E8000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F0000, 0);
- kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F8000, 0);
- for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
- kvm_msr_entry_add(cpu, MSR_MTRRphysBase(i), 0);
- kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), 0);
- }
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
- if (ret < 0) {
- return ret;
- }
-
- assert(ret == cpu->kvm_msr_buf->nmsrs);
- /*
- * MTRR masks: Each mask consists of 5 parts
- * a 10..0: must be zero
- * b 11 : valid bit
- * c n-1.12: actual mask bits
- * d 51..n: reserved must be zero
- * e 63.52: reserved must be zero
- *
- * 'n' is the number of physical bits supported by the CPU and is
- * apparently always <= 52. We know our 'n' but don't know what
- * the destinations 'n' is; it might be smaller, in which case
- * it masks (c) on loading. It might be larger, in which case
- * we fill 'd' so that d..c is consistent irrespetive of the 'n'
- * we're migrating to.
- */
-
- if (cpu->fill_mtrr_mask) {
- QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > 52);
- assert(cpu->phys_bits <= TARGET_PHYS_ADDR_SPACE_BITS);
- mtrr_top_bits = MAKE_64BIT_MASK(cpu->phys_bits, 52 - cpu->phys_bits);
- } else {
- mtrr_top_bits = 0;
- }
-
- for (i = 0; i < ret; i++) {
- uint32_t index = msrs[i].index;
- switch (index) {
- case MSR_IA32_SYSENTER_CS:
- env->sysenter_cs = msrs[i].data;
- break;
- case MSR_IA32_SYSENTER_ESP:
- env->sysenter_esp = msrs[i].data;
- break;
- case MSR_IA32_SYSENTER_EIP:
- env->sysenter_eip = msrs[i].data;
- break;
- case MSR_PAT:
- env->pat = msrs[i].data;
- break;
- case MSR_STAR:
- env->star = msrs[i].data;
- break;
-#ifdef TARGET_X86_64
- case MSR_CSTAR:
- env->cstar = msrs[i].data;
- break;
- case MSR_KERNELGSBASE:
- env->kernelgsbase = msrs[i].data;
- break;
- case MSR_FMASK:
- env->fmask = msrs[i].data;
- break;
- case MSR_LSTAR:
- env->lstar = msrs[i].data;
- break;
-#endif
- case MSR_IA32_TSC:
- env->tsc = msrs[i].data;
- break;
- case MSR_TSC_AUX:
- env->tsc_aux = msrs[i].data;
- break;
- case MSR_TSC_ADJUST:
- env->tsc_adjust = msrs[i].data;
- break;
- case MSR_IA32_TSCDEADLINE:
- env->tsc_deadline = msrs[i].data;
- break;
- case MSR_VM_HSAVE_PA:
- env->vm_hsave = msrs[i].data;
- break;
- case MSR_KVM_SYSTEM_TIME:
- env->system_time_msr = msrs[i].data;
- break;
- case MSR_KVM_WALL_CLOCK:
- env->wall_clock_msr = msrs[i].data;
- break;
- case MSR_MCG_STATUS:
- env->mcg_status = msrs[i].data;
- break;
- case MSR_MCG_CTL:
- env->mcg_ctl = msrs[i].data;
- break;
- case MSR_MCG_EXT_CTL:
- env->mcg_ext_ctl = msrs[i].data;
- break;
- case MSR_IA32_MISC_ENABLE:
- env->msr_ia32_misc_enable = msrs[i].data;
- break;
- case MSR_IA32_SMBASE:
- env->smbase = msrs[i].data;
- break;
- case MSR_IA32_FEATURE_CONTROL:
- env->msr_ia32_feature_control = msrs[i].data;
- break;
- case MSR_IA32_BNDCFGS:
- env->msr_bndcfgs = msrs[i].data;
- break;
- case MSR_IA32_XSS:
- env->xss = msrs[i].data;
- break;
- default:
- if (msrs[i].index >= MSR_MC0_CTL &&
- msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
- env->mce_banks[msrs[i].index - MSR_MC0_CTL] = msrs[i].data;
- }
- break;
- case MSR_KVM_ASYNC_PF_EN:
- env->async_pf_en_msr = msrs[i].data;
- break;
- case MSR_KVM_PV_EOI_EN:
- env->pv_eoi_en_msr = msrs[i].data;
- break;
- case MSR_KVM_STEAL_TIME:
- env->steal_time_msr = msrs[i].data;
- break;
- case MSR_CORE_PERF_FIXED_CTR_CTRL:
- env->msr_fixed_ctr_ctrl = msrs[i].data;
- break;
- case MSR_CORE_PERF_GLOBAL_CTRL:
- env->msr_global_ctrl = msrs[i].data;
- break;
- case MSR_CORE_PERF_GLOBAL_STATUS:
- env->msr_global_status = msrs[i].data;
- break;
- case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- env->msr_global_ovf_ctrl = msrs[i].data;
- break;
- case MSR_CORE_PERF_FIXED_CTR0 ... MSR_CORE_PERF_FIXED_CTR0 + MAX_FIXED_COUNTERS - 1:
- env->msr_fixed_counters[index - MSR_CORE_PERF_FIXED_CTR0] = msrs[i].data;
- break;
- case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR0 + MAX_GP_COUNTERS - 1:
- env->msr_gp_counters[index - MSR_P6_PERFCTR0] = msrs[i].data;
- break;
- case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL0 + MAX_GP_COUNTERS - 1:
- env->msr_gp_evtsel[index - MSR_P6_EVNTSEL0] = msrs[i].data;
- break;
- case HV_X64_MSR_HYPERCALL:
- env->msr_hv_hypercall = msrs[i].data;
- break;
- case HV_X64_MSR_GUEST_OS_ID:
- env->msr_hv_guest_os_id = msrs[i].data;
- break;
- case HV_X64_MSR_APIC_ASSIST_PAGE:
- env->msr_hv_vapic = msrs[i].data;
- break;
- case HV_X64_MSR_REFERENCE_TSC:
- env->msr_hv_tsc = msrs[i].data;
- break;
- case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
- env->msr_hv_crash_params[index - HV_X64_MSR_CRASH_P0] = msrs[i].data;
- break;
- case HV_X64_MSR_VP_RUNTIME:
- env->msr_hv_runtime = msrs[i].data;
- break;
- case HV_X64_MSR_SCONTROL:
- env->msr_hv_synic_control = msrs[i].data;
- break;
- case HV_X64_MSR_SVERSION:
- env->msr_hv_synic_version = msrs[i].data;
- break;
- case HV_X64_MSR_SIEFP:
- env->msr_hv_synic_evt_page = msrs[i].data;
- break;
- case HV_X64_MSR_SIMP:
- env->msr_hv_synic_msg_page = msrs[i].data;
- break;
- case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
- env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
- break;
- case HV_X64_MSR_STIMER0_CONFIG:
- case HV_X64_MSR_STIMER1_CONFIG:
- case HV_X64_MSR_STIMER2_CONFIG:
- case HV_X64_MSR_STIMER3_CONFIG:
- env->msr_hv_stimer_config[(index - HV_X64_MSR_STIMER0_CONFIG)/2] =
- msrs[i].data;
- break;
- case HV_X64_MSR_STIMER0_COUNT:
- case HV_X64_MSR_STIMER1_COUNT:
- case HV_X64_MSR_STIMER2_COUNT:
- case HV_X64_MSR_STIMER3_COUNT:
- env->msr_hv_stimer_count[(index - HV_X64_MSR_STIMER0_COUNT)/2] =
- msrs[i].data;
- break;
- case MSR_MTRRdefType:
- env->mtrr_deftype = msrs[i].data;
- break;
- case MSR_MTRRfix64K_00000:
- env->mtrr_fixed[0] = msrs[i].data;
- break;
- case MSR_MTRRfix16K_80000:
- env->mtrr_fixed[1] = msrs[i].data;
- break;
- case MSR_MTRRfix16K_A0000:
- env->mtrr_fixed[2] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_C0000:
- env->mtrr_fixed[3] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_C8000:
- env->mtrr_fixed[4] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_D0000:
- env->mtrr_fixed[5] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_D8000:
- env->mtrr_fixed[6] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_E0000:
- env->mtrr_fixed[7] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_E8000:
- env->mtrr_fixed[8] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_F0000:
- env->mtrr_fixed[9] = msrs[i].data;
- break;
- case MSR_MTRRfix4K_F8000:
- env->mtrr_fixed[10] = msrs[i].data;
- break;
- case MSR_MTRRphysBase(0) ... MSR_MTRRphysMask(MSR_MTRRcap_VCNT - 1):
- if (index & 1) {
- env->mtrr_var[MSR_MTRRphysIndex(index)].mask = msrs[i].data |
- mtrr_top_bits;
- } else {
- env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data;
- }
- break;
- }
- }
-
- return 0;
-}
-
-static int kvm_put_mp_state(X86CPU *cpu)
-{
- struct kvm_mp_state mp_state = { .mp_state = cpu->env.mp_state };
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
-}
-
-static int kvm_get_mp_state(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- struct kvm_mp_state mp_state;
- int ret;
-
- ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
- if (ret < 0) {
- return ret;
- }
- env->mp_state = mp_state.mp_state;
- if (kvm_irqchip_in_kernel()) {
- cs->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
- }
- return 0;
-}
-
-static int kvm_get_apic(X86CPU *cpu)
-{
- DeviceState *apic = cpu->apic_state;
- struct kvm_lapic_state kapic;
- int ret;
-
- if (apic && kvm_irqchip_in_kernel()) {
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_LAPIC, &kapic);
- if (ret < 0) {
- return ret;
- }
-
- kvm_get_apic_state(apic, &kapic);
- }
- return 0;
-}
-
-static int kvm_put_vcpu_events(X86CPU *cpu, int level)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- struct kvm_vcpu_events events = {};
-
- if (!kvm_has_vcpu_events()) {
- return 0;
- }
-
- events.exception.injected = (env->exception_injected >= 0);
- events.exception.nr = env->exception_injected;
- events.exception.has_error_code = env->has_error_code;
- events.exception.error_code = env->error_code;
- events.exception.pad = 0;
-
- events.interrupt.injected = (env->interrupt_injected >= 0);
- events.interrupt.nr = env->interrupt_injected;
- events.interrupt.soft = env->soft_interrupt;
-
- events.nmi.injected = env->nmi_injected;
- events.nmi.pending = env->nmi_pending;
- events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
- events.nmi.pad = 0;
-
- events.sipi_vector = env->sipi_vector;
- events.flags = 0;
-
- if (has_msr_smbase) {
- events.smi.smm = !!(env->hflags & HF_SMM_MASK);
- events.smi.smm_inside_nmi = !!(env->hflags2 & HF2_SMM_INSIDE_NMI_MASK);
- if (kvm_irqchip_in_kernel()) {
- /* As soon as these are moved to the kernel, remove them
- * from cs->interrupt_request.
- */
- events.smi.pending = cs->interrupt_request & CPU_INTERRUPT_SMI;
- events.smi.latched_init = cs->interrupt_request & CPU_INTERRUPT_INIT;
- cs->interrupt_request &= ~(CPU_INTERRUPT_INIT | CPU_INTERRUPT_SMI);
- } else {
- /* Keep these in cs->interrupt_request. */
- events.smi.pending = 0;
- events.smi.latched_init = 0;
- }
- events.flags |= KVM_VCPUEVENT_VALID_SMM;
- }
-
- if (level >= KVM_PUT_RESET_STATE) {
- events.flags |=
- KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR;
- }
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events);
-}
-
-static int kvm_get_vcpu_events(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_vcpu_events events;
- int ret;
-
- if (!kvm_has_vcpu_events()) {
- return 0;
- }
-
- memset(&events, 0, sizeof(events));
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events);
- if (ret < 0) {
- return ret;
- }
- env->exception_injected =
- events.exception.injected ? events.exception.nr : -1;
- env->has_error_code = events.exception.has_error_code;
- env->error_code = events.exception.error_code;
-
- env->interrupt_injected =
- events.interrupt.injected ? events.interrupt.nr : -1;
- env->soft_interrupt = events.interrupt.soft;
-
- env->nmi_injected = events.nmi.injected;
- env->nmi_pending = events.nmi.pending;
- if (events.nmi.masked) {
- env->hflags2 |= HF2_NMI_MASK;
- } else {
- env->hflags2 &= ~HF2_NMI_MASK;
- }
-
- if (events.flags & KVM_VCPUEVENT_VALID_SMM) {
- if (events.smi.smm) {
- env->hflags |= HF_SMM_MASK;
- } else {
- env->hflags &= ~HF_SMM_MASK;
- }
- if (events.smi.pending) {
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
- } else {
- cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
- }
- if (events.smi.smm_inside_nmi) {
- env->hflags2 |= HF2_SMM_INSIDE_NMI_MASK;
- } else {
- env->hflags2 &= ~HF2_SMM_INSIDE_NMI_MASK;
- }
- if (events.smi.latched_init) {
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_INIT);
- } else {
- cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_INIT);
- }
- }
-
- env->sipi_vector = events.sipi_vector;
-
- return 0;
-}
-
-static int kvm_guest_debug_workarounds(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- int ret = 0;
- unsigned long reinject_trap = 0;
-
- if (!kvm_has_vcpu_events()) {
- if (env->exception_injected == 1) {
- reinject_trap = KVM_GUESTDBG_INJECT_DB;
- } else if (env->exception_injected == 3) {
- reinject_trap = KVM_GUESTDBG_INJECT_BP;
- }
- env->exception_injected = -1;
- }
-
- /*
- * Kernels before KVM_CAP_X86_ROBUST_SINGLESTEP overwrote flags.TF
- * injected via SET_GUEST_DEBUG while updating GP regs. Work around this
- * by updating the debug state once again if single-stepping is on.
- * Another reason to call kvm_update_guest_debug here is a pending debug
- * trap raise by the guest. On kernels without SET_VCPU_EVENTS we have to
- * reinject them via SET_GUEST_DEBUG.
- */
- if (reinject_trap ||
- (!kvm_has_robust_singlestep() && cs->singlestep_enabled)) {
- ret = kvm_update_guest_debug(cs, reinject_trap);
- }
- return ret;
-}
-
-static int kvm_put_debugregs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_debugregs dbgregs;
- int i;
-
- if (!kvm_has_debugregs()) {
- return 0;
- }
-
- for (i = 0; i < 4; i++) {
- dbgregs.db[i] = env->dr[i];
- }
- dbgregs.dr6 = env->dr[6];
- dbgregs.dr7 = env->dr[7];
- dbgregs.flags = 0;
-
- return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEBUGREGS, &dbgregs);
-}
-
-static int kvm_get_debugregs(X86CPU *cpu)
-{
- CPUX86State *env = &cpu->env;
- struct kvm_debugregs dbgregs;
- int i, ret;
-
- if (!kvm_has_debugregs()) {
- return 0;
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEBUGREGS, &dbgregs);
- if (ret < 0) {
- return ret;
- }
- for (i = 0; i < 4; i++) {
- env->dr[i] = dbgregs.db[i];
- }
- env->dr[4] = env->dr[6] = dbgregs.dr6;
- env->dr[5] = env->dr[7] = dbgregs.dr7;
-
- return 0;
-}
-
-int kvm_arch_put_registers(CPUState *cpu, int level)
-{
- X86CPU *x86_cpu = X86_CPU(cpu);
- int ret;
-
- assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
-
- if (level >= KVM_PUT_RESET_STATE) {
- ret = kvm_put_msr_feature_control(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- }
-
- if (level == KVM_PUT_FULL_STATE) {
- /* We don't check for kvm_arch_set_tsc_khz() errors here,
- * because TSC frequency mismatch shouldn't abort migration,
- * unless the user explicitly asked for a more strict TSC
- * setting (e.g. using an explicit "tsc-freq" option).
- */
- kvm_arch_set_tsc_khz(cpu);
- }
-
- ret = kvm_getput_regs(x86_cpu, 1);
- if (ret < 0) {
- return ret;
- }
- ret = kvm_put_xsave(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- ret = kvm_put_xcrs(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- ret = kvm_put_sregs(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- /* must be before kvm_put_msrs */
- ret = kvm_inject_mce_oldstyle(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- ret = kvm_put_msrs(x86_cpu, level);
- if (ret < 0) {
- return ret;
- }
- if (level >= KVM_PUT_RESET_STATE) {
- ret = kvm_put_mp_state(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- }
-
- ret = kvm_put_tscdeadline_msr(x86_cpu);
- if (ret < 0) {
- return ret;
- }
-
- ret = kvm_put_vcpu_events(x86_cpu, level);
- if (ret < 0) {
- return ret;
- }
- ret = kvm_put_debugregs(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- /* must be last */
- ret = kvm_guest_debug_workarounds(x86_cpu);
- if (ret < 0) {
- return ret;
- }
- return 0;
-}
-
-int kvm_arch_get_registers(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- int ret;
-
- assert(cpu_is_stopped(cs) || qemu_cpu_is_self(cs));
-
- ret = kvm_getput_regs(cpu, 0);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_xsave(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_xcrs(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_sregs(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_msrs(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_mp_state(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_apic(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_vcpu_events(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = kvm_get_debugregs(cpu);
- if (ret < 0) {
- goto out;
- }
- ret = 0;
- out:
- cpu_sync_bndcs_hflags(&cpu->env);
- return ret;
-}
-
-void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
-{
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
- int ret;
-
- /* Inject NMI */
- if (cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
- if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
- qemu_mutex_lock_iothread();
- cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
- qemu_mutex_unlock_iothread();
- DPRINTF("injected NMI\n");
- ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
- if (ret < 0) {
- fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
- strerror(-ret));
- }
- }
- if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
- qemu_mutex_lock_iothread();
- cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
- qemu_mutex_unlock_iothread();
- DPRINTF("injected SMI\n");
- ret = kvm_vcpu_ioctl(cpu, KVM_SMI);
- if (ret < 0) {
- fprintf(stderr, "KVM: injection failed, SMI lost (%s)\n",
- strerror(-ret));
- }
- }
- }
-
- if (!kvm_pic_in_kernel()) {
- qemu_mutex_lock_iothread();
- }
-
- /* Force the VCPU out of its inner loop to process any INIT requests
- * or (for userspace APIC, but it is cheap to combine the checks here)
- * pending TPR access reports.
- */
- if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
- if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
- !(env->hflags & HF_SMM_MASK)) {
- cpu->exit_request = 1;
- }
- if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
- cpu->exit_request = 1;
- }
- }
-
- if (!kvm_pic_in_kernel()) {
- /* Try to inject an interrupt if the guest can accept it */
- if (run->ready_for_interrupt_injection &&
- (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) {
- int irq;
-
- cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
- irq = cpu_get_pic_interrupt(env);
- if (irq >= 0) {
- struct kvm_interrupt intr;
-
- intr.irq = irq;
- DPRINTF("injected interrupt %d\n", irq);
- ret = kvm_vcpu_ioctl(cpu, KVM_INTERRUPT, &intr);
- if (ret < 0) {
- fprintf(stderr,
- "KVM: injection failed, interrupt lost (%s)\n",
- strerror(-ret));
- }
- }
- }
-
- /* If we have an interrupt but the guest is not ready to receive an
- * interrupt, request an interrupt window exit. This will
- * cause a return to userspace as soon as the guest is ready to
- * receive interrupts. */
- if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
- run->request_interrupt_window = 1;
- } else {
- run->request_interrupt_window = 0;
- }
-
- DPRINTF("setting tpr\n");
- run->cr8 = cpu_get_apic_tpr(x86_cpu->apic_state);
-
- qemu_mutex_unlock_iothread();
- }
-}
-
-MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
-{
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
-
- if (run->flags & KVM_RUN_X86_SMM) {
- env->hflags |= HF_SMM_MASK;
- } else {
- env->hflags &= ~HF_SMM_MASK;
- }
- if (run->if_flag) {
- env->eflags |= IF_MASK;
- } else {
- env->eflags &= ~IF_MASK;
- }
-
- /* We need to protect the apic state against concurrent accesses from
- * different threads in case the userspace irqchip is used. */
- if (!kvm_irqchip_in_kernel()) {
- qemu_mutex_lock_iothread();
- }
- cpu_set_apic_tpr(x86_cpu->apic_state, run->cr8);
- cpu_set_apic_base(x86_cpu->apic_state, run->apic_base);
- if (!kvm_irqchip_in_kernel()) {
- qemu_mutex_unlock_iothread();
- }
- return cpu_get_mem_attrs(env);
-}
-
-int kvm_arch_process_async_events(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- if (cs->interrupt_request & CPU_INTERRUPT_MCE) {
- /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
- assert(env->mcg_cap);
-
- cs->interrupt_request &= ~CPU_INTERRUPT_MCE;
-
- kvm_cpu_synchronize_state(cs);
-
- if (env->exception_injected == EXCP08_DBLE) {
- /* this means triple fault */
- qemu_system_reset_request();
- cs->exit_request = 1;
- return 0;
- }
- env->exception_injected = EXCP12_MCHK;
- env->has_error_code = 0;
-
- cs->halted = 0;
- if (kvm_irqchip_in_kernel() && env->mp_state == KVM_MP_STATE_HALTED) {
- env->mp_state = KVM_MP_STATE_RUNNABLE;
- }
- }
-
- if ((cs->interrupt_request & CPU_INTERRUPT_INIT) &&
- !(env->hflags & HF_SMM_MASK)) {
- kvm_cpu_synchronize_state(cs);
- do_cpu_init(cpu);
- }
-
- if (kvm_irqchip_in_kernel()) {
- return 0;
- }
-
- if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
- cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
- apic_poll_irq(cpu->apic_state);
- }
- if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) ||
- (cs->interrupt_request & CPU_INTERRUPT_NMI)) {
- cs->halted = 0;
- }
- if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
- kvm_cpu_synchronize_state(cs);
- do_cpu_sipi(cpu);
- }
- if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
- cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
- kvm_cpu_synchronize_state(cs);
- apic_handle_tpr_access_report(cpu->apic_state, env->eip,
- env->tpr_access_type);
- }
-
- return cs->halted;
-}
-
-static int kvm_handle_halt(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
-
- if (!((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) &&
- !(cs->interrupt_request & CPU_INTERRUPT_NMI)) {
- cs->halted = 1;
- return EXCP_HLT;
- }
-
- return 0;
-}
-
-static int kvm_handle_tpr_access(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_run *run = cs->kvm_run;
-
- apic_handle_tpr_access_report(cpu->apic_state, run->tpr_access.rip,
- run->tpr_access.is_write ? TPR_ACCESS_WRITE
- : TPR_ACCESS_READ);
- return 1;
-}
-
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
- static const uint8_t int3 = 0xcc;
-
- if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
- cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&int3, 1, 1)) {
- return -EINVAL;
- }
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3;
-
- if (cpu_memory_rw_debug(cs, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
- cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
- return -EINVAL;
- }
- return 0;
-}
-
-static struct {
- target_ulong addr;
- int len;
- int type;
-} hw_breakpoint[4];
-
-static int nb_hw_breakpoint;
-
-static int find_hw_breakpoint(target_ulong addr, int len, int type)
-{
- int n;
-
- for (n = 0; n < nb_hw_breakpoint; n++) {
- if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
- (hw_breakpoint[n].len == len || len == -1)) {
- return n;
- }
- }
- return -1;
-}
-
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- switch (type) {
- case GDB_BREAKPOINT_HW:
- len = 1;
- break;
- case GDB_WATCHPOINT_WRITE:
- case GDB_WATCHPOINT_ACCESS:
- switch (len) {
- case 1:
- break;
- case 2:
- case 4:
- case 8:
- if (addr & (len - 1)) {
- return -EINVAL;
- }
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -ENOSYS;
- }
-
- if (nb_hw_breakpoint == 4) {
- return -ENOBUFS;
- }
- if (find_hw_breakpoint(addr, len, type) >= 0) {
- return -EEXIST;
- }
- hw_breakpoint[nb_hw_breakpoint].addr = addr;
- hw_breakpoint[nb_hw_breakpoint].len = len;
- hw_breakpoint[nb_hw_breakpoint].type = type;
- nb_hw_breakpoint++;
-
- return 0;
-}
-
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- int n;
-
- n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
- if (n < 0) {
- return -ENOENT;
- }
- nb_hw_breakpoint--;
- hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
-
- return 0;
-}
-
-void kvm_arch_remove_all_hw_breakpoints(void)
-{
- nb_hw_breakpoint = 0;
-}
-
-static CPUWatchpoint hw_watchpoint;
-
-static int kvm_handle_debug(X86CPU *cpu,
- struct kvm_debug_exit_arch *arch_info)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- int ret = 0;
- int n;
-
- if (arch_info->exception == 1) {
- if (arch_info->dr6 & (1 << 14)) {
- if (cs->singlestep_enabled) {
- ret = EXCP_DEBUG;
- }
- } else {
- for (n = 0; n < 4; n++) {
- if (arch_info->dr6 & (1 << n)) {
- switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
- case 0x0:
- ret = EXCP_DEBUG;
- break;
- case 0x1:
- ret = EXCP_DEBUG;
- cs->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_WRITE;
- break;
- case 0x3:
- ret = EXCP_DEBUG;
- cs->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_ACCESS;
- break;
- }
- }
- }
- }
- } else if (kvm_find_sw_breakpoint(cs, arch_info->pc)) {
- ret = EXCP_DEBUG;
- }
- if (ret == 0) {
- cpu_synchronize_state(cs);
- assert(env->exception_injected == -1);
-
- /* pass to guest */
- env->exception_injected = arch_info->exception;
- env->has_error_code = 0;
- }
-
- return ret;
-}
-
-void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
-{
- const uint8_t type_code[] = {
- [GDB_BREAKPOINT_HW] = 0x0,
- [GDB_WATCHPOINT_WRITE] = 0x1,
- [GDB_WATCHPOINT_ACCESS] = 0x3
- };
- const uint8_t len_code[] = {
- [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
- };
- int n;
-
- if (kvm_sw_breakpoints_active(cpu)) {
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
- }
- if (nb_hw_breakpoint > 0) {
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
- dbg->arch.debugreg[7] = 0x0600;
- for (n = 0; n < nb_hw_breakpoint; n++) {
- dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
- dbg->arch.debugreg[7] |= (2 << (n * 2)) |
- (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
- ((uint32_t)len_code[hw_breakpoint[n].len] << (18 + n*4));
- }
- }
-}
-
-static bool host_supports_vmx(void)
-{
- uint32_t ecx, unused;
-
- host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
- return ecx & CPUID_EXT_VMX;
-}
-
-#define VMX_INVALID_GUEST_STATE 0x80000021
-
-int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
-{
- X86CPU *cpu = X86_CPU(cs);
- uint64_t code;
- int ret;
-
- switch (run->exit_reason) {
- case KVM_EXIT_HLT:
- DPRINTF("handle_hlt\n");
- qemu_mutex_lock_iothread();
- ret = kvm_handle_halt(cpu);
- qemu_mutex_unlock_iothread();
- break;
- case KVM_EXIT_SET_TPR:
- ret = 0;
- break;
- case KVM_EXIT_TPR_ACCESS:
- qemu_mutex_lock_iothread();
- ret = kvm_handle_tpr_access(cpu);
- qemu_mutex_unlock_iothread();
- break;
- case KVM_EXIT_FAIL_ENTRY:
- code = run->fail_entry.hardware_entry_failure_reason;
- fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
- code);
- if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
- fprintf(stderr,
- "\nIf you're running a guest on an Intel machine without "
- "unrestricted mode\n"
- "support, the failure can be most likely due to the guest "
- "entering an invalid\n"
- "state for Intel VT. For example, the guest maybe running "
- "in big real mode\n"
- "which is not supported on less recent Intel processors."
- "\n\n");
- }
- ret = -1;
- break;
- case KVM_EXIT_EXCEPTION:
- fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
- run->ex.exception, run->ex.error_code);
- ret = -1;
- break;
- case KVM_EXIT_DEBUG:
- DPRINTF("kvm_exit_debug\n");
- qemu_mutex_lock_iothread();
- ret = kvm_handle_debug(cpu, &run->debug.arch);
- qemu_mutex_unlock_iothread();
- break;
- case KVM_EXIT_HYPERV:
- ret = kvm_hv_handle_exit(cpu, &run->hyperv);
- break;
- case KVM_EXIT_IOAPIC_EOI:
- ioapic_eoi_broadcast(run->eoi.vector);
- ret = 0;
- break;
- default:
- fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-bool kvm_arch_stop_on_emulation_error(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- kvm_cpu_synchronize_state(cs);
- return !(env->cr[0] & CR0_PE_MASK) ||
- ((env->segs[R_CS].selector & 3) != 3);
-}
-
-void kvm_arch_init_irq_routing(KVMState *s)
-{
- if (!kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
- /* If kernel can't do irq routing, interrupt source
- * override 0->2 cannot be set up as required by HPET.
- * So we have to disable it.
- */
- no_hpet = 1;
- }
- /* We know at this point that we're using the in-kernel
- * irqchip, so we can use irqfds, and on x86 we know
- * we can use msi via irqfd and GSI routing.
- */
- kvm_msi_via_irqfd_allowed = true;
- kvm_gsi_routing_allowed = true;
-
- if (kvm_irqchip_is_split()) {
- int i;
-
- /* If the ioapic is in QEMU and the lapics are in KVM, reserve
- MSI routes for signaling interrupts to the local apics. */
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- if (kvm_irqchip_add_msi_route(s, 0, NULL) < 0) {
- error_report("Could not enable split IRQ mode.");
- exit(1);
- }
- }
- }
-}
-
-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
-{
- int ret;
- if (machine_kernel_irqchip_split(ms)) {
- ret = kvm_vm_enable_cap(s, KVM_CAP_SPLIT_IRQCHIP, 0, 24);
- if (ret) {
- error_report("Could not enable split irqchip mode: %s",
- strerror(-ret));
- exit(1);
- } else {
- DPRINTF("Enabled KVM_CAP_SPLIT_IRQCHIP\n");
- kvm_split_irqchip = true;
- return 1;
- }
- } else {
- return 0;
- }
-}
-
-/* Classic KVM device assignment interface. Will remain x86 only. */
-int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr,
- uint32_t flags, uint32_t *dev_id)
-{
- struct kvm_assigned_pci_dev dev_data = {
- .segnr = dev_addr->domain,
- .busnr = dev_addr->bus,
- .devfn = PCI_DEVFN(dev_addr->slot, dev_addr->function),
- .flags = flags,
- };
- int ret;
-
- dev_data.assigned_dev_id =
- (dev_addr->domain << 16) | (dev_addr->bus << 8) | dev_data.devfn;
-
- ret = kvm_vm_ioctl(s, KVM_ASSIGN_PCI_DEVICE, &dev_data);
- if (ret < 0) {
- return ret;
- }
-
- *dev_id = dev_data.assigned_dev_id;
-
- return 0;
-}
-
-int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id)
-{
- struct kvm_assigned_pci_dev dev_data = {
- .assigned_dev_id = dev_id,
- };
-
- return kvm_vm_ioctl(s, KVM_DEASSIGN_PCI_DEVICE, &dev_data);
-}
-
-static int kvm_assign_irq_internal(KVMState *s, uint32_t dev_id,
- uint32_t irq_type, uint32_t guest_irq)
-{
- struct kvm_assigned_irq assigned_irq = {
- .assigned_dev_id = dev_id,
- .guest_irq = guest_irq,
- .flags = irq_type,
- };
-
- if (kvm_check_extension(s, KVM_CAP_ASSIGN_DEV_IRQ)) {
- return kvm_vm_ioctl(s, KVM_ASSIGN_DEV_IRQ, &assigned_irq);
- } else {
- return kvm_vm_ioctl(s, KVM_ASSIGN_IRQ, &assigned_irq);
- }
-}
-
-int kvm_device_intx_assign(KVMState *s, uint32_t dev_id, bool use_host_msi,
- uint32_t guest_irq)
-{
- uint32_t irq_type = KVM_DEV_IRQ_GUEST_INTX |
- (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX);
-
- return kvm_assign_irq_internal(s, dev_id, irq_type, guest_irq);
-}
-
-int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked)
-{
- struct kvm_assigned_pci_dev dev_data = {
- .assigned_dev_id = dev_id,
- .flags = masked ? KVM_DEV_ASSIGN_MASK_INTX : 0,
- };
-
- return kvm_vm_ioctl(s, KVM_ASSIGN_SET_INTX_MASK, &dev_data);
-}
-
-static int kvm_deassign_irq_internal(KVMState *s, uint32_t dev_id,
- uint32_t type)
-{
- struct kvm_assigned_irq assigned_irq = {
- .assigned_dev_id = dev_id,
- .flags = type,
- };
-
- return kvm_vm_ioctl(s, KVM_DEASSIGN_DEV_IRQ, &assigned_irq);
-}
-
-int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi)
-{
- return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_INTX |
- (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX));
-}
-
-int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq)
-{
- return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSI |
- KVM_DEV_IRQ_GUEST_MSI, virq);
-}
-
-int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id)
-{
- return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSI |
- KVM_DEV_IRQ_HOST_MSI);
-}
-
-bool kvm_device_msix_supported(KVMState *s)
-{
- /* The kernel lacks a corresponding KVM_CAP, so we probe by calling
- * KVM_ASSIGN_SET_MSIX_NR with an invalid parameter. */
- return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, NULL) == -EFAULT;
-}
-
-int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id,
- uint32_t nr_vectors)
-{
- struct kvm_assigned_msix_nr msix_nr = {
- .assigned_dev_id = dev_id,
- .entry_nr = nr_vectors,
- };
-
- return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, &msix_nr);
-}
-
-int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector,
- int virq)
-{
- struct kvm_assigned_msix_entry msix_entry = {
- .assigned_dev_id = dev_id,
- .gsi = virq,
- .entry = vector,
- };
-
- return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_ENTRY, &msix_entry);
-}
-
-int kvm_device_msix_assign(KVMState *s, uint32_t dev_id)
-{
- return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSIX |
- KVM_DEV_IRQ_GUEST_MSIX, 0);
-}
-
-int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id)
-{
- return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX |
- KVM_DEV_IRQ_HOST_MSIX);
-}
-
-int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data, PCIDevice *dev)
-{
- X86IOMMUState *iommu = x86_iommu_get_default();
-
- if (iommu) {
- int ret;
- MSIMessage src, dst;
- X86IOMMUClass *class = X86_IOMMU_GET_CLASS(iommu);
-
- src.address = route->u.msi.address_hi;
- src.address <<= VTD_MSI_ADDR_HI_SHIFT;
- src.address |= route->u.msi.address_lo;
- src.data = route->u.msi.data;
-
- ret = class->int_remap(iommu, &src, &dst, dev ? \
- pci_requester_id(dev) : \
- X86_IOMMU_SID_INVALID);
- if (ret) {
- trace_kvm_x86_fixup_msi_error(route->gsi);
- return 1;
- }
-
- route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT;
- route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK;
- route->u.msi.data = dst.data;
- }
-
- return 0;
-}
-
-typedef struct MSIRouteEntry MSIRouteEntry;
-
-struct MSIRouteEntry {
- PCIDevice *dev; /* Device pointer */
- int vector; /* MSI/MSIX vector index */
- int virq; /* Virtual IRQ index */
- QLIST_ENTRY(MSIRouteEntry) list;
-};
-
-/* List of used GSI routes */
-static QLIST_HEAD(, MSIRouteEntry) msi_route_list = \
- QLIST_HEAD_INITIALIZER(msi_route_list);
-
-static void kvm_update_msi_routes_all(void *private, bool global,
- uint32_t index, uint32_t mask)
-{
- int cnt = 0;
- MSIRouteEntry *entry;
- MSIMessage msg;
- /* TODO: explicit route update */
- QLIST_FOREACH(entry, &msi_route_list, list) {
- cnt++;
- msg = pci_get_msi_message(entry->dev, entry->vector);
- kvm_irqchip_update_msi_route(kvm_state, entry->virq,
- msg, entry->dev);
- }
- kvm_irqchip_commit_routes(kvm_state);
- trace_kvm_x86_update_msi_routes(cnt);
-}
-
-int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
- int vector, PCIDevice *dev)
-{
- static bool notify_list_inited = false;
- MSIRouteEntry *entry;
-
- if (!dev) {
- /* These are (possibly) IOAPIC routes only used for split
- * kernel irqchip mode, while what we are housekeeping are
- * PCI devices only. */
- return 0;
- }
-
- entry = g_new0(MSIRouteEntry, 1);
- entry->dev = dev;
- entry->vector = vector;
- entry->virq = route->gsi;
- QLIST_INSERT_HEAD(&msi_route_list, entry, list);
-
- trace_kvm_x86_add_msi_route(route->gsi);
-
- if (!notify_list_inited) {
- /* For the first time we do add route, add ourselves into
- * IOMMU's IEC notify list if needed. */
- X86IOMMUState *iommu = x86_iommu_get_default();
- if (iommu) {
- x86_iommu_iec_register_notifier(iommu,
- kvm_update_msi_routes_all,
- NULL);
- }
- notify_list_inited = true;
- }
- return 0;
-}
-
-int kvm_arch_release_virq_post(int virq)
-{
- MSIRouteEntry *entry, *next;
- QLIST_FOREACH_SAFE(entry, &msi_route_list, list, next) {
- if (entry->virq == virq) {
- trace_kvm_x86_remove_msi_route(virq);
- QLIST_REMOVE(entry, list);
- break;
- }
- }
- return 0;
-}
-
-int kvm_arch_msi_data_to_gsi(uint32_t data)
-{
- abort();
-}
diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h
deleted file mode 100644
index 76079295b2..0000000000
--- a/target-i386/kvm_i386.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * QEMU KVM support -- x86 specific functions.
- *
- * Copyright (c) 2012 Linaro Limited
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef QEMU_KVM_I386_H
-#define QEMU_KVM_I386_H
-
-#include "sysemu/kvm.h"
-
-#define kvm_apic_in_kernel() (kvm_irqchip_in_kernel())
-
-bool kvm_allows_irq0_override(void);
-bool kvm_has_smm(void);
-void kvm_synchronize_all_tsc(void);
-void kvm_arch_reset_vcpu(X86CPU *cs);
-void kvm_arch_do_init_vcpu(X86CPU *cs);
-
-int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr,
- uint32_t flags, uint32_t *dev_id);
-int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id);
-
-int kvm_device_intx_assign(KVMState *s, uint32_t dev_id,
- bool use_host_msi, uint32_t guest_irq);
-int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked);
-int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi);
-
-int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq);
-int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id);
-
-bool kvm_device_msix_supported(KVMState *s);
-int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id,
- uint32_t nr_vectors);
-int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector,
- int virq);
-int kvm_device_msix_assign(KVMState *s, uint32_t dev_id);
-int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);
-
-void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
-
-bool kvm_enable_x2apic(void);
-bool kvm_has_x2apic_api(void);
-#endif
diff --git a/target-i386/machine.c b/target-i386/machine.c
deleted file mode 100644
index 760f82b6c7..0000000000
--- a/target-i386/machine.c
+++ /dev/null
@@ -1,1047 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "hw/hw.h"
-#include "hw/boards.h"
-#include "hw/i386/pc.h"
-#include "hw/isa/isa.h"
-#include "migration/cpu.h"
-
-#include "sysemu/kvm.h"
-
-#include "qemu/error-report.h"
-
-static const VMStateDescription vmstate_segment = {
- .name = "segment",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(selector, SegmentCache),
- VMSTATE_UINTTL(base, SegmentCache),
- VMSTATE_UINT32(limit, SegmentCache),
- VMSTATE_UINT32(flags, SegmentCache),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_SEGMENT(_field, _state) { \
- .name = (stringify(_field)), \
- .size = sizeof(SegmentCache), \
- .vmsd = &vmstate_segment, \
- .flags = VMS_STRUCT, \
- .offset = offsetof(_state, _field) \
- + type_check(SegmentCache,typeof_field(_state, _field)) \
-}
-
-#define VMSTATE_SEGMENT_ARRAY(_field, _state, _n) \
- VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_segment, SegmentCache)
-
-static const VMStateDescription vmstate_xmm_reg = {
- .name = "xmm_reg",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(ZMM_Q(0), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(1), ZMMReg),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_XMM_REGS(_field, _state, _start) \
- VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \
- vmstate_xmm_reg, ZMMReg)
-
-/* YMMH format is the same as XMM, but for bits 128-255 */
-static const VMStateDescription vmstate_ymmh_reg = {
- .name = "ymmh_reg",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(ZMM_Q(2), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(3), ZMMReg),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_YMMH_REGS_VARS(_field, _state, _start, _v) \
- VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, _v, \
- vmstate_ymmh_reg, ZMMReg)
-
-static const VMStateDescription vmstate_zmmh_reg = {
- .name = "zmmh_reg",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(ZMM_Q(4), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(5), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(6), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(7), ZMMReg),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _start) \
- VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \
- vmstate_zmmh_reg, ZMMReg)
-
-#ifdef TARGET_X86_64
-static const VMStateDescription vmstate_hi16_zmm_reg = {
- .name = "hi16_zmm_reg",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(ZMM_Q(0), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(1), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(2), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(3), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(4), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(5), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(6), ZMMReg),
- VMSTATE_UINT64(ZMM_Q(7), ZMMReg),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _start) \
- VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \
- vmstate_hi16_zmm_reg, ZMMReg)
-#endif
-
-static const VMStateDescription vmstate_bnd_regs = {
- .name = "bnd_regs",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(lb, BNDReg),
- VMSTATE_UINT64(ub, BNDReg),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_BND_REGS(_field, _state, _n) \
- VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_bnd_regs, BNDReg)
-
-static const VMStateDescription vmstate_mtrr_var = {
- .name = "mtrr_var",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(base, MTRRVar),
- VMSTATE_UINT64(mask, MTRRVar),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \
- VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
-
-static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
-{
- fprintf(stderr, "call put_fpreg() with invalid arguments\n");
- exit(0);
-}
-
-/* XXX: add that in a FPU generic layer */
-union x86_longdouble {
- uint64_t mant;
- uint16_t exp;
-};
-
-#define MANTD1(fp) (fp & ((1LL << 52) - 1))
-#define EXPBIAS1 1023
-#define EXPD1(fp) ((fp >> 52) & 0x7FF)
-#define SIGND1(fp) ((fp >> 32) & 0x80000000)
-
-static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
-{
- int e;
- /* mantissa */
- p->mant = (MANTD1(temp) << 11) | (1LL << 63);
- /* exponent + sign */
- e = EXPD1(temp) - EXPBIAS1 + 16383;
- e |= SIGND1(temp) >> 16;
- p->exp = e;
-}
-
-static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
-{
- FPReg *fp_reg = opaque;
- uint64_t mant;
- uint16_t exp;
-
- qemu_get_be64s(f, &mant);
- qemu_get_be16s(f, &exp);
- fp_reg->d = cpu_set_fp80(mant, exp);
- return 0;
-}
-
-static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
-{
- FPReg *fp_reg = opaque;
- uint64_t mant;
- uint16_t exp;
- /* we save the real CPU data (in case of MMX usage only 'mant'
- contains the MMX register */
- cpu_get_fp80(&mant, &exp, fp_reg->d);
- qemu_put_be64s(f, &mant);
- qemu_put_be16s(f, &exp);
-}
-
-static const VMStateInfo vmstate_fpreg = {
- .name = "fpreg",
- .get = get_fpreg,
- .put = put_fpreg,
-};
-
-static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
-{
- union x86_longdouble *p = opaque;
- uint64_t mant;
-
- qemu_get_be64s(f, &mant);
- p->mant = mant;
- p->exp = 0xffff;
- return 0;
-}
-
-static const VMStateInfo vmstate_fpreg_1_mmx = {
- .name = "fpreg_1_mmx",
- .get = get_fpreg_1_mmx,
- .put = put_fpreg_error,
-};
-
-static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
-{
- union x86_longdouble *p = opaque;
- uint64_t mant;
-
- qemu_get_be64s(f, &mant);
- fp64_to_fp80(p, mant);
- return 0;
-}
-
-static const VMStateInfo vmstate_fpreg_1_no_mmx = {
- .name = "fpreg_1_no_mmx",
- .get = get_fpreg_1_no_mmx,
- .put = put_fpreg_error,
-};
-
-static bool fpregs_is_0(void *opaque, int version_id)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return (env->fpregs_format_vmstate == 0);
-}
-
-static bool fpregs_is_1_mmx(void *opaque, int version_id)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int guess_mmx;
-
- guess_mmx = ((env->fptag_vmstate == 0xff) &&
- (env->fpus_vmstate & 0x3800) == 0);
- return (guess_mmx && (env->fpregs_format_vmstate == 1));
-}
-
-static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int guess_mmx;
-
- guess_mmx = ((env->fptag_vmstate == 0xff) &&
- (env->fpus_vmstate & 0x3800) == 0);
- return (!guess_mmx && (env->fpregs_format_vmstate == 1));
-}
-
-#define VMSTATE_FP_REGS(_field, _state, _n) \
- VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0, vmstate_fpreg, FPReg), \
- VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_mmx, vmstate_fpreg_1_mmx, FPReg), \
- VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_no_mmx, vmstate_fpreg_1_no_mmx, FPReg)
-
-static bool version_is_5(void *opaque, int version_id)
-{
- return version_id == 5;
-}
-
-#ifdef TARGET_X86_64
-static bool less_than_7(void *opaque, int version_id)
-{
- return version_id < 7;
-}
-
-static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
-{
- uint64_t *v = pv;
- *v = qemu_get_be32(f);
- return 0;
-}
-
-static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
-{
- uint64_t *v = pv;
- qemu_put_be32(f, *v);
-}
-
-static const VMStateInfo vmstate_hack_uint64_as_uint32 = {
- .name = "uint64_as_uint32",
- .get = get_uint64_as_uint32,
- .put = put_uint64_as_uint32,
-};
-
-#define VMSTATE_HACK_UINT32(_f, _s, _t) \
- VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint64_as_uint32, uint64_t)
-#endif
-
-static void cpu_pre_save(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int i;
-
- /* FPU */
- env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- env->fptag_vmstate = 0;
- for(i = 0; i < 8; i++) {
- env->fptag_vmstate |= ((!env->fptags[i]) << i);
- }
-
- env->fpregs_format_vmstate = 0;
-
- /*
- * Real mode guest segments register DPL should be zero.
- * Older KVM version were setting it wrongly.
- * Fixing it will allow live migration to host with unrestricted guest
- * support (otherwise the migration will fail with invalid guest state
- * error).
- */
- if (!(env->cr[0] & CR0_PE_MASK) &&
- (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) {
- env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK);
- env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK);
- env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK);
- env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK);
- env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK);
- env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
- }
-
-}
-
-static int cpu_post_load(void *opaque, int version_id)
-{
- X86CPU *cpu = opaque;
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- int i;
-
- if (env->tsc_khz && env->user_tsc_khz &&
- env->tsc_khz != env->user_tsc_khz) {
- error_report("Mismatch between user-specified TSC frequency and "
- "migrated TSC frequency");
- return -EINVAL;
- }
-
- /*
- * Real mode guest segments register DPL should be zero.
- * Older KVM version were setting it wrongly.
- * Fixing it will allow live migration from such host that don't have
- * restricted guest support to a host with unrestricted guest support
- * (otherwise the migration will fail with invalid guest state
- * error).
- */
- if (!(env->cr[0] & CR0_PE_MASK) &&
- (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) {
- env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK);
- env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK);
- env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK);
- env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK);
- env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK);
- env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
- }
-
- /* Older versions of QEMU incorrectly used CS.DPL as the CPL when
- * running under KVM. This is wrong for conforming code segments.
- * Luckily, in our implementation the CPL field of hflags is redundant
- * and we can get the right value from the SS descriptor privilege level.
- */
- env->hflags &= ~HF_CPL_MASK;
- env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
-
- env->fpstt = (env->fpus_vmstate >> 11) & 7;
- env->fpus = env->fpus_vmstate & ~0x3800;
- env->fptag_vmstate ^= 0xff;
- for(i = 0; i < 8; i++) {
- env->fptags[i] = (env->fptag_vmstate >> i) & 1;
- }
- update_fp_status(env);
-
- cpu_breakpoint_remove_all(cs, BP_CPU);
- cpu_watchpoint_remove_all(cs, BP_CPU);
- {
- /* Indicate all breakpoints disabled, as they are, then
- let the helper re-enable them. */
- target_ulong dr7 = env->dr[7];
- env->dr[7] = dr7 & ~(DR7_GLOBAL_BP_MASK | DR7_LOCAL_BP_MASK);
- cpu_x86_update_dr7(env, dr7);
- }
- tlb_flush(cs, 1);
-
- if (tcg_enabled()) {
- cpu_smm_update(cpu);
- }
- return 0;
-}
-
-static bool async_pf_msr_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
-
- return cpu->env.async_pf_en_msr != 0;
-}
-
-static bool pv_eoi_msr_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
-
- return cpu->env.pv_eoi_en_msr != 0;
-}
-
-static bool steal_time_msr_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
-
- return cpu->env.steal_time_msr != 0;
-}
-
-static const VMStateDescription vmstate_steal_time_msr = {
- .name = "cpu/steal_time_msr",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = steal_time_msr_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.steal_time_msr, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_async_pf_msr = {
- .name = "cpu/async_pf_msr",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = async_pf_msr_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.async_pf_en_msr, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_pv_eoi_msr = {
- .name = "cpu/async_pv_eoi_msr",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = pv_eoi_msr_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.pv_eoi_en_msr, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool fpop_ip_dp_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->fpop != 0 || env->fpip != 0 || env->fpdp != 0;
-}
-
-static const VMStateDescription vmstate_fpop_ip_dp = {
- .name = "cpu/fpop_ip_dp",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = fpop_ip_dp_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16(env.fpop, X86CPU),
- VMSTATE_UINT64(env.fpip, X86CPU),
- VMSTATE_UINT64(env.fpdp, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool tsc_adjust_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->tsc_adjust != 0;
-}
-
-static const VMStateDescription vmstate_msr_tsc_adjust = {
- .name = "cpu/msr_tsc_adjust",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = tsc_adjust_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.tsc_adjust, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool tscdeadline_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->tsc_deadline != 0;
-}
-
-static const VMStateDescription vmstate_msr_tscdeadline = {
- .name = "cpu/msr_tscdeadline",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = tscdeadline_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.tsc_deadline, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool misc_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT;
-}
-
-static bool feature_control_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->msr_ia32_feature_control != 0;
-}
-
-static const VMStateDescription vmstate_msr_ia32_misc_enable = {
- .name = "cpu/msr_ia32_misc_enable",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = misc_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_ia32_misc_enable, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_msr_ia32_feature_control = {
- .name = "cpu/msr_ia32_feature_control",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = feature_control_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool pmu_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int i;
-
- if (env->msr_fixed_ctr_ctrl || env->msr_global_ctrl ||
- env->msr_global_status || env->msr_global_ovf_ctrl) {
- return true;
- }
- for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
- if (env->msr_fixed_counters[i]) {
- return true;
- }
- }
- for (i = 0; i < MAX_GP_COUNTERS; i++) {
- if (env->msr_gp_counters[i] || env->msr_gp_evtsel[i]) {
- return true;
- }
- }
-
- return false;
-}
-
-static const VMStateDescription vmstate_msr_architectural_pmu = {
- .name = "cpu/msr_architectural_pmu",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = pmu_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU),
- VMSTATE_UINT64(env.msr_global_ctrl, X86CPU),
- VMSTATE_UINT64(env.msr_global_status, X86CPU),
- VMSTATE_UINT64(env.msr_global_ovf_ctrl, X86CPU),
- VMSTATE_UINT64_ARRAY(env.msr_fixed_counters, X86CPU, MAX_FIXED_COUNTERS),
- VMSTATE_UINT64_ARRAY(env.msr_gp_counters, X86CPU, MAX_GP_COUNTERS),
- VMSTATE_UINT64_ARRAY(env.msr_gp_evtsel, X86CPU, MAX_GP_COUNTERS),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool mpx_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- unsigned int i;
-
- for (i = 0; i < 4; i++) {
- if (env->bnd_regs[i].lb || env->bnd_regs[i].ub) {
- return true;
- }
- }
-
- if (env->bndcs_regs.cfgu || env->bndcs_regs.sts) {
- return true;
- }
-
- return !!env->msr_bndcfgs;
-}
-
-static const VMStateDescription vmstate_mpx = {
- .name = "cpu/mpx",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = mpx_needed,
- .fields = (VMStateField[]) {
- VMSTATE_BND_REGS(env.bnd_regs, X86CPU, 4),
- VMSTATE_UINT64(env.bndcs_regs.cfgu, X86CPU),
- VMSTATE_UINT64(env.bndcs_regs.sts, X86CPU),
- VMSTATE_UINT64(env.msr_bndcfgs, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_hypercall_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->msr_hv_hypercall != 0 || env->msr_hv_guest_os_id != 0;
-}
-
-static const VMStateDescription vmstate_msr_hypercall_hypercall = {
- .name = "cpu/msr_hyperv_hypercall",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_hypercall_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU),
- VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_vapic_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->msr_hv_vapic != 0;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_vapic = {
- .name = "cpu/msr_hyperv_vapic",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_vapic_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_hv_vapic, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_time_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->msr_hv_tsc != 0;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_time = {
- .name = "cpu/msr_hyperv_time",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_time_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_hv_tsc, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_crash_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int i;
-
- for (i = 0; i < HV_X64_MSR_CRASH_PARAMS; i++) {
- if (env->msr_hv_crash_params[i]) {
- return true;
- }
- }
- return false;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_crash = {
- .name = "cpu/msr_hyperv_crash",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_crash_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64_ARRAY(env.msr_hv_crash_params,
- X86CPU, HV_X64_MSR_CRASH_PARAMS),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_runtime_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- if (!cpu->hyperv_runtime) {
- return false;
- }
-
- return env->msr_hv_runtime != 0;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_runtime = {
- .name = "cpu/msr_hyperv_runtime",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_runtime_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_hv_runtime, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_synic_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int i;
-
- if (env->msr_hv_synic_control != 0 ||
- env->msr_hv_synic_evt_page != 0 ||
- env->msr_hv_synic_msg_page != 0) {
- return true;
- }
-
- for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
- if (env->msr_hv_synic_sint[i] != 0) {
- return true;
- }
- }
-
- return false;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_synic = {
- .name = "cpu/msr_hyperv_synic",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_synic_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
- VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
- VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
- VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
- HV_SYNIC_SINT_COUNT),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool hyperv_stimer_enable_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(env->msr_hv_stimer_config); i++) {
- if (env->msr_hv_stimer_config[i] || env->msr_hv_stimer_count[i]) {
- return true;
- }
- }
- return false;
-}
-
-static const VMStateDescription vmstate_msr_hyperv_stimer = {
- .name = "cpu/msr_hyperv_stimer",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hyperv_stimer_enable_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_config,
- X86CPU, HV_SYNIC_STIMER_COUNT),
- VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_count,
- X86CPU, HV_SYNIC_STIMER_COUNT),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool avx512_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- unsigned int i;
-
- for (i = 0; i < NB_OPMASK_REGS; i++) {
- if (env->opmask_regs[i]) {
- return true;
- }
- }
-
- for (i = 0; i < CPU_NB_REGS; i++) {
-#define ENV_XMM(reg, field) (env->xmm_regs[reg].ZMM_Q(field))
- if (ENV_XMM(i, 4) || ENV_XMM(i, 6) ||
- ENV_XMM(i, 5) || ENV_XMM(i, 7)) {
- return true;
- }
-#ifdef TARGET_X86_64
- if (ENV_XMM(i+16, 0) || ENV_XMM(i+16, 1) ||
- ENV_XMM(i+16, 2) || ENV_XMM(i+16, 3) ||
- ENV_XMM(i+16, 4) || ENV_XMM(i+16, 5) ||
- ENV_XMM(i+16, 6) || ENV_XMM(i+16, 7)) {
- return true;
- }
-#endif
- }
-
- return false;
-}
-
-static const VMStateDescription vmstate_avx512 = {
- .name = "cpu/avx512",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = avx512_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS),
- VMSTATE_ZMMH_REGS_VARS(env.xmm_regs, X86CPU, 0),
-#ifdef TARGET_X86_64
- VMSTATE_Hi16_ZMM_REGS_VARS(env.xmm_regs, X86CPU, 16),
-#endif
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool xss_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->xss != 0;
-}
-
-static const VMStateDescription vmstate_xss = {
- .name = "cpu/xss",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = xss_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.xss, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#ifdef TARGET_X86_64
-static bool pkru_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
-
- return env->pkru != 0;
-}
-
-static const VMStateDescription vmstate_pkru = {
- .name = "cpu/pkru",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = pkru_needed,
- .fields = (VMStateField[]){
- VMSTATE_UINT32(env.pkru, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-#endif
-
-static bool tsc_khz_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
- PCMachineClass *pcmc = PC_MACHINE_CLASS(mc);
- return env->tsc_khz && pcmc->save_tsc_khz;
-}
-
-static const VMStateDescription vmstate_tsc_khz = {
- .name = "cpu/tsc_khz",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = tsc_khz_needed,
- .fields = (VMStateField[]) {
- VMSTATE_INT64(env.tsc_khz, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool mcg_ext_ctl_needed(void *opaque)
-{
- X86CPU *cpu = opaque;
- CPUX86State *env = &cpu->env;
- return cpu->enable_lmce && env->mcg_ext_ctl;
-}
-
-static const VMStateDescription vmstate_mcg_ext_ctl = {
- .name = "cpu/mcg_ext_ctl",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = mcg_ext_ctl_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.mcg_ext_ctl, X86CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-VMStateDescription vmstate_x86_cpu = {
- .name = "cpu",
- .version_id = 12,
- .minimum_version_id = 3,
- .pre_save = cpu_pre_save,
- .post_load = cpu_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINTTL_ARRAY(env.regs, X86CPU, CPU_NB_REGS),
- VMSTATE_UINTTL(env.eip, X86CPU),
- VMSTATE_UINTTL(env.eflags, X86CPU),
- VMSTATE_UINT32(env.hflags, X86CPU),
- /* FPU */
- VMSTATE_UINT16(env.fpuc, X86CPU),
- VMSTATE_UINT16(env.fpus_vmstate, X86CPU),
- VMSTATE_UINT16(env.fptag_vmstate, X86CPU),
- VMSTATE_UINT16(env.fpregs_format_vmstate, X86CPU),
- VMSTATE_FP_REGS(env.fpregs, X86CPU, 8),
-
- VMSTATE_SEGMENT_ARRAY(env.segs, X86CPU, 6),
- VMSTATE_SEGMENT(env.ldt, X86CPU),
- VMSTATE_SEGMENT(env.tr, X86CPU),
- VMSTATE_SEGMENT(env.gdt, X86CPU),
- VMSTATE_SEGMENT(env.idt, X86CPU),
-
- VMSTATE_UINT32(env.sysenter_cs, X86CPU),
-#ifdef TARGET_X86_64
- /* Hack: In v7 size changed from 32 to 64 bits on x86_64 */
- VMSTATE_HACK_UINT32(env.sysenter_esp, X86CPU, less_than_7),
- VMSTATE_HACK_UINT32(env.sysenter_eip, X86CPU, less_than_7),
- VMSTATE_UINTTL_V(env.sysenter_esp, X86CPU, 7),
- VMSTATE_UINTTL_V(env.sysenter_eip, X86CPU, 7),
-#else
- VMSTATE_UINTTL(env.sysenter_esp, X86CPU),
- VMSTATE_UINTTL(env.sysenter_eip, X86CPU),
-#endif
-
- VMSTATE_UINTTL(env.cr[0], X86CPU),
- VMSTATE_UINTTL(env.cr[2], X86CPU),
- VMSTATE_UINTTL(env.cr[3], X86CPU),
- VMSTATE_UINTTL(env.cr[4], X86CPU),
- VMSTATE_UINTTL_ARRAY(env.dr, X86CPU, 8),
- /* MMU */
- VMSTATE_INT32(env.a20_mask, X86CPU),
- /* XMM */
- VMSTATE_UINT32(env.mxcsr, X86CPU),
- VMSTATE_XMM_REGS(env.xmm_regs, X86CPU, 0),
-
-#ifdef TARGET_X86_64
- VMSTATE_UINT64(env.efer, X86CPU),
- VMSTATE_UINT64(env.star, X86CPU),
- VMSTATE_UINT64(env.lstar, X86CPU),
- VMSTATE_UINT64(env.cstar, X86CPU),
- VMSTATE_UINT64(env.fmask, X86CPU),
- VMSTATE_UINT64(env.kernelgsbase, X86CPU),
-#endif
- VMSTATE_UINT32_V(env.smbase, X86CPU, 4),
-
- VMSTATE_UINT64_V(env.pat, X86CPU, 5),
- VMSTATE_UINT32_V(env.hflags2, X86CPU, 5),
-
- VMSTATE_UINT32_TEST(parent_obj.halted, X86CPU, version_is_5),
- VMSTATE_UINT64_V(env.vm_hsave, X86CPU, 5),
- VMSTATE_UINT64_V(env.vm_vmcb, X86CPU, 5),
- VMSTATE_UINT64_V(env.tsc_offset, X86CPU, 5),
- VMSTATE_UINT64_V(env.intercept, X86CPU, 5),
- VMSTATE_UINT16_V(env.intercept_cr_read, X86CPU, 5),
- VMSTATE_UINT16_V(env.intercept_cr_write, X86CPU, 5),
- VMSTATE_UINT16_V(env.intercept_dr_read, X86CPU, 5),
- VMSTATE_UINT16_V(env.intercept_dr_write, X86CPU, 5),
- VMSTATE_UINT32_V(env.intercept_exceptions, X86CPU, 5),
- VMSTATE_UINT8_V(env.v_tpr, X86CPU, 5),
- /* MTRRs */
- VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8),
- VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8),
- VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, MSR_MTRRcap_VCNT, 8),
- /* KVM-related states */
- VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9),
- VMSTATE_UINT32_V(env.mp_state, X86CPU, 9),
- VMSTATE_UINT64_V(env.tsc, X86CPU, 9),
- VMSTATE_INT32_V(env.exception_injected, X86CPU, 11),
- VMSTATE_UINT8_V(env.soft_interrupt, X86CPU, 11),
- VMSTATE_UINT8_V(env.nmi_injected, X86CPU, 11),
- VMSTATE_UINT8_V(env.nmi_pending, X86CPU, 11),
- VMSTATE_UINT8_V(env.has_error_code, X86CPU, 11),
- VMSTATE_UINT32_V(env.sipi_vector, X86CPU, 11),
- /* MCE */
- VMSTATE_UINT64_V(env.mcg_cap, X86CPU, 10),
- VMSTATE_UINT64_V(env.mcg_status, X86CPU, 10),
- VMSTATE_UINT64_V(env.mcg_ctl, X86CPU, 10),
- VMSTATE_UINT64_ARRAY_V(env.mce_banks, X86CPU, MCE_BANKS_DEF * 4, 10),
- /* rdtscp */
- VMSTATE_UINT64_V(env.tsc_aux, X86CPU, 11),
- /* KVM pvclock msr */
- VMSTATE_UINT64_V(env.system_time_msr, X86CPU, 11),
- VMSTATE_UINT64_V(env.wall_clock_msr, X86CPU, 11),
- /* XSAVE related fields */
- VMSTATE_UINT64_V(env.xcr0, X86CPU, 12),
- VMSTATE_UINT64_V(env.xstate_bv, X86CPU, 12),
- VMSTATE_YMMH_REGS_VARS(env.xmm_regs, X86CPU, 0, 12),
- VMSTATE_END_OF_LIST()
- /* The above list is not sorted /wrt version numbers, watch out! */
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_async_pf_msr,
- &vmstate_pv_eoi_msr,
- &vmstate_steal_time_msr,
- &vmstate_fpop_ip_dp,
- &vmstate_msr_tsc_adjust,
- &vmstate_msr_tscdeadline,
- &vmstate_msr_ia32_misc_enable,
- &vmstate_msr_ia32_feature_control,
- &vmstate_msr_architectural_pmu,
- &vmstate_mpx,
- &vmstate_msr_hypercall_hypercall,
- &vmstate_msr_hyperv_vapic,
- &vmstate_msr_hyperv_time,
- &vmstate_msr_hyperv_crash,
- &vmstate_msr_hyperv_runtime,
- &vmstate_msr_hyperv_synic,
- &vmstate_msr_hyperv_stimer,
- &vmstate_avx512,
- &vmstate_xss,
- &vmstate_tsc_khz,
-#ifdef TARGET_X86_64
- &vmstate_pkru,
-#endif
- &vmstate_mcg_ext_ctl,
- NULL
- }
-};
diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c
deleted file mode 100644
index 70f67668ab..0000000000
--- a/target-i386/mem_helper.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * x86 memory access helpers
- *
- * 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 "cpu.h"
-#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
-#include "qemu/int128.h"
-#include "tcg.h"
-
-void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0)
-{
- uintptr_t ra = GETPC();
- uint64_t oldv, cmpv, newv;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
-
- cmpv = deposit64(env->regs[R_EAX], 32, 32, env->regs[R_EDX]);
- newv = deposit64(env->regs[R_EBX], 32, 32, env->regs[R_ECX]);
-
- oldv = cpu_ldq_data_ra(env, a0, ra);
- newv = (cmpv == oldv ? newv : oldv);
- /* always do the store */
- cpu_stq_data_ra(env, a0, newv, ra);
-
- if (oldv == cmpv) {
- eflags |= CC_Z;
- } else {
- env->regs[R_EAX] = (uint32_t)oldv;
- env->regs[R_EDX] = (uint32_t)(oldv >> 32);
- eflags &= ~CC_Z;
- }
- CC_SRC = eflags;
-}
-
-void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
-{
-#ifdef CONFIG_ATOMIC64
- uint64_t oldv, cmpv, newv;
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
-
- cmpv = deposit64(env->regs[R_EAX], 32, 32, env->regs[R_EDX]);
- newv = deposit64(env->regs[R_EBX], 32, 32, env->regs[R_ECX]);
-
-#ifdef CONFIG_USER_ONLY
- {
- uint64_t *haddr = g2h(a0);
- cmpv = cpu_to_le64(cmpv);
- newv = cpu_to_le64(newv);
- oldv = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
- oldv = le64_to_cpu(oldv);
- }
-#else
- {
- uintptr_t ra = GETPC();
- int mem_idx = cpu_mmu_index(env, false);
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ, mem_idx);
- oldv = helper_atomic_cmpxchgq_le_mmu(env, a0, cmpv, newv, oi, ra);
- }
-#endif
-
- if (oldv == cmpv) {
- eflags |= CC_Z;
- } else {
- env->regs[R_EAX] = (uint32_t)oldv;
- env->regs[R_EDX] = (uint32_t)(oldv >> 32);
- eflags &= ~CC_Z;
- }
- CC_SRC = eflags;
-#else
- cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
-#endif /* CONFIG_ATOMIC64 */
-}
-
-#ifdef TARGET_X86_64
-void helper_cmpxchg16b_unlocked(CPUX86State *env, target_ulong a0)
-{
- uintptr_t ra = GETPC();
- Int128 oldv, cmpv, newv;
- uint64_t o0, o1;
- int eflags;
- bool success;
-
- if ((a0 & 0xf) != 0) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
- eflags = cpu_cc_compute_all(env, CC_OP);
-
- cmpv = int128_make128(env->regs[R_EAX], env->regs[R_EDX]);
- newv = int128_make128(env->regs[R_EBX], env->regs[R_ECX]);
-
- o0 = cpu_ldq_data_ra(env, a0 + 0, ra);
- o1 = cpu_ldq_data_ra(env, a0 + 8, ra);
-
- oldv = int128_make128(o0, o1);
- success = int128_eq(oldv, cmpv);
- if (!success) {
- newv = oldv;
- }
-
- cpu_stq_data_ra(env, a0 + 0, int128_getlo(newv), ra);
- cpu_stq_data_ra(env, a0 + 8, int128_gethi(newv), ra);
-
- if (success) {
- eflags |= CC_Z;
- } else {
- env->regs[R_EAX] = int128_getlo(oldv);
- env->regs[R_EDX] = int128_gethi(oldv);
- eflags &= ~CC_Z;
- }
- CC_SRC = eflags;
-}
-
-void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
-{
- uintptr_t ra = GETPC();
-
- if ((a0 & 0xf) != 0) {
- raise_exception_ra(env, EXCP0D_GPF, ra);
- } else {
-#ifndef CONFIG_ATOMIC128
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
-#else
- int eflags = cpu_cc_compute_all(env, CC_OP);
-
- Int128 cmpv = int128_make128(env->regs[R_EAX], env->regs[R_EDX]);
- Int128 newv = int128_make128(env->regs[R_EBX], env->regs[R_ECX]);
-
- int mem_idx = cpu_mmu_index(env, false);
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
- Int128 oldv = helper_atomic_cmpxchgo_le_mmu(env, a0, cmpv,
- newv, oi, ra);
-
- if (int128_eq(oldv, cmpv)) {
- eflags |= CC_Z;
- } else {
- env->regs[R_EAX] = int128_getlo(oldv);
- env->regs[R_EDX] = int128_gethi(oldv);
- eflags &= ~CC_Z;
- }
- CC_SRC = eflags;
-#endif
- }
-}
-#endif
-
-void helper_boundw(CPUX86State *env, target_ulong a0, int v)
-{
- int low, high;
-
- low = cpu_ldsw_data_ra(env, a0, GETPC());
- high = cpu_ldsw_data_ra(env, a0 + 2, GETPC());
- v = (int16_t)v;
- if (v < low || v > high) {
- if (env->hflags & HF_MPX_EN_MASK) {
- env->bndcs_regs.sts = 0;
- }
- raise_exception_ra(env, EXCP05_BOUND, GETPC());
- }
-}
-
-void helper_boundl(CPUX86State *env, target_ulong a0, int v)
-{
- int low, high;
-
- low = cpu_ldl_data_ra(env, a0, GETPC());
- high = cpu_ldl_data_ra(env, a0 + 4, GETPC());
- if (v < low || v > high) {
- if (env->hflags & HF_MPX_EN_MASK) {
- env->bndcs_regs.sts = 0;
- }
- raise_exception_ra(env, EXCP05_BOUND, GETPC());
- }
-}
-
-#if !defined(CONFIG_USER_ONLY)
-/* try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = x86_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
- if (ret) {
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr);
- }
-}
-#endif
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
deleted file mode 100644
index 3f666b4b87..0000000000
--- a/target-i386/misc_helper.c
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * x86 misc helpers
- *
- * 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 "cpu.h"
-#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
-#include "exec/address-spaces.h"
-
-void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
-#else
- address_space_stb(&address_space_io, port, data,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-target_ulong helper_inb(CPUX86State *env, uint32_t port)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "inb: port=0x%04x\n", port);
- return 0;
-#else
- return address_space_ldub(&address_space_io, port,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
-#else
- address_space_stw(&address_space_io, port, data,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-target_ulong helper_inw(CPUX86State *env, uint32_t port)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "inw: port=0x%04x\n", port);
- return 0;
-#else
- return address_space_lduw(&address_space_io, port,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "outw: port=0x%04x, data=%08x\n", port, data);
-#else
- address_space_stl(&address_space_io, port, data,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-target_ulong helper_inl(CPUX86State *env, uint32_t port)
-{
-#ifdef CONFIG_USER_ONLY
- fprintf(stderr, "inl: port=0x%04x\n", port);
- return 0;
-#else
- return address_space_ldl(&address_space_io, port,
- cpu_get_mem_attrs(env), NULL);
-#endif
-}
-
-void helper_into(CPUX86State *env, int next_eip_addend)
-{
- int eflags;
-
- eflags = cpu_cc_compute_all(env, CC_OP);
- if (eflags & CC_O) {
- raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
- }
-}
-
-void helper_cpuid(CPUX86State *env)
-{
- uint32_t eax, ebx, ecx, edx;
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
-
- cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
- &eax, &ebx, &ecx, &edx);
- env->regs[R_EAX] = eax;
- env->regs[R_EBX] = ebx;
- env->regs[R_ECX] = ecx;
- env->regs[R_EDX] = edx;
-}
-
-#if defined(CONFIG_USER_ONLY)
-target_ulong helper_read_crN(CPUX86State *env, int reg)
-{
- return 0;
-}
-
-void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
-{
-}
-#else
-target_ulong helper_read_crN(CPUX86State *env, int reg)
-{
- target_ulong val;
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0);
- switch (reg) {
- default:
- val = env->cr[reg];
- break;
- case 8:
- if (!(env->hflags2 & HF2_VINTR_MASK)) {
- val = cpu_get_apic_tpr(x86_env_get_cpu(env)->apic_state);
- } else {
- val = env->v_tpr;
- }
- break;
- }
- return val;
-}
-
-void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
-{
- cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0);
- switch (reg) {
- case 0:
- cpu_x86_update_cr0(env, t0);
- break;
- case 3:
- cpu_x86_update_cr3(env, t0);
- break;
- case 4:
- cpu_x86_update_cr4(env, t0);
- break;
- case 8:
- if (!(env->hflags2 & HF2_VINTR_MASK)) {
- cpu_set_apic_tpr(x86_env_get_cpu(env)->apic_state, t0);
- }
- env->v_tpr = t0 & 0x0f;
- break;
- default:
- env->cr[reg] = t0;
- break;
- }
-}
-#endif
-
-void helper_lmsw(CPUX86State *env, target_ulong t0)
-{
- /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
- if already set to one. */
- t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
- helper_write_crN(env, 0, t0);
-}
-
-void helper_invlpg(CPUX86State *env, target_ulong addr)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
- tlb_flush_page(CPU(cpu), addr);
-}
-
-void helper_rdtsc(CPUX86State *env)
-{
- uint64_t val;
-
- if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
- cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
-
- val = cpu_get_tsc(env) + env->tsc_offset;
- env->regs[R_EAX] = (uint32_t)(val);
- env->regs[R_EDX] = (uint32_t)(val >> 32);
-}
-
-void helper_rdtscp(CPUX86State *env)
-{
- helper_rdtsc(env);
- env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
-}
-
-void helper_rdpmc(CPUX86State *env)
-{
- if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
- cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
-
- /* currently unimplemented */
- qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
- raise_exception_err(env, EXCP06_ILLOP, 0);
-}
-
-#if defined(CONFIG_USER_ONLY)
-void helper_wrmsr(CPUX86State *env)
-{
-}
-
-void helper_rdmsr(CPUX86State *env)
-{
-}
-#else
-void helper_wrmsr(CPUX86State *env)
-{
- uint64_t val;
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1);
-
- val = ((uint32_t)env->regs[R_EAX]) |
- ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
-
- switch ((uint32_t)env->regs[R_ECX]) {
- case MSR_IA32_SYSENTER_CS:
- env->sysenter_cs = val & 0xffff;
- break;
- case MSR_IA32_SYSENTER_ESP:
- env->sysenter_esp = val;
- break;
- case MSR_IA32_SYSENTER_EIP:
- env->sysenter_eip = val;
- break;
- case MSR_IA32_APICBASE:
- cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val);
- break;
- case MSR_EFER:
- {
- uint64_t update_mask;
-
- update_mask = 0;
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
- update_mask |= MSR_EFER_SCE;
- }
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
- update_mask |= MSR_EFER_LME;
- }
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
- update_mask |= MSR_EFER_FFXSR;
- }
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
- update_mask |= MSR_EFER_NXE;
- }
- if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
- update_mask |= MSR_EFER_SVME;
- }
- if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
- update_mask |= MSR_EFER_FFXSR;
- }
- cpu_load_efer(env, (env->efer & ~update_mask) |
- (val & update_mask));
- }
- break;
- case MSR_STAR:
- env->star = val;
- break;
- case MSR_PAT:
- env->pat = val;
- break;
- case MSR_VM_HSAVE_PA:
- env->vm_hsave = val;
- break;
-#ifdef TARGET_X86_64
- case MSR_LSTAR:
- env->lstar = val;
- break;
- case MSR_CSTAR:
- env->cstar = val;
- break;
- case MSR_FMASK:
- env->fmask = val;
- break;
- case MSR_FSBASE:
- env->segs[R_FS].base = val;
- break;
- case MSR_GSBASE:
- env->segs[R_GS].base = val;
- break;
- case MSR_KERNELGSBASE:
- env->kernelgsbase = val;
- break;
-#endif
- case MSR_MTRRphysBase(0):
- case MSR_MTRRphysBase(1):
- case MSR_MTRRphysBase(2):
- case MSR_MTRRphysBase(3):
- case MSR_MTRRphysBase(4):
- case MSR_MTRRphysBase(5):
- case MSR_MTRRphysBase(6):
- case MSR_MTRRphysBase(7):
- env->mtrr_var[((uint32_t)env->regs[R_ECX] -
- MSR_MTRRphysBase(0)) / 2].base = val;
- break;
- case MSR_MTRRphysMask(0):
- case MSR_MTRRphysMask(1):
- case MSR_MTRRphysMask(2):
- case MSR_MTRRphysMask(3):
- case MSR_MTRRphysMask(4):
- case MSR_MTRRphysMask(5):
- case MSR_MTRRphysMask(6):
- case MSR_MTRRphysMask(7):
- env->mtrr_var[((uint32_t)env->regs[R_ECX] -
- MSR_MTRRphysMask(0)) / 2].mask = val;
- break;
- case MSR_MTRRfix64K_00000:
- env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
- MSR_MTRRfix64K_00000] = val;
- break;
- case MSR_MTRRfix16K_80000:
- case MSR_MTRRfix16K_A0000:
- env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
- MSR_MTRRfix16K_80000 + 1] = val;
- break;
- case MSR_MTRRfix4K_C0000:
- case MSR_MTRRfix4K_C8000:
- case MSR_MTRRfix4K_D0000:
- case MSR_MTRRfix4K_D8000:
- case MSR_MTRRfix4K_E0000:
- case MSR_MTRRfix4K_E8000:
- case MSR_MTRRfix4K_F0000:
- case MSR_MTRRfix4K_F8000:
- env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
- MSR_MTRRfix4K_C0000 + 3] = val;
- break;
- case MSR_MTRRdefType:
- env->mtrr_deftype = val;
- break;
- case MSR_MCG_STATUS:
- env->mcg_status = val;
- break;
- case MSR_MCG_CTL:
- if ((env->mcg_cap & MCG_CTL_P)
- && (val == 0 || val == ~(uint64_t)0)) {
- env->mcg_ctl = val;
- }
- break;
- case MSR_TSC_AUX:
- env->tsc_aux = val;
- break;
- case MSR_IA32_MISC_ENABLE:
- env->msr_ia32_misc_enable = val;
- break;
- case MSR_IA32_BNDCFGS:
- /* FIXME: #GP if reserved bits are set. */
- /* FIXME: Extend highest implemented bit of linear address. */
- env->msr_bndcfgs = val;
- cpu_sync_bndcs_hflags(env);
- break;
- default:
- if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
- && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
- (4 * env->mcg_cap & 0xff)) {
- uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
- if ((offset & 0x3) != 0
- || (val == 0 || val == ~(uint64_t)0)) {
- env->mce_banks[offset] = val;
- }
- break;
- }
- /* XXX: exception? */
- break;
- }
-}
-
-void helper_rdmsr(CPUX86State *env)
-{
- uint64_t val;
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0);
-
- switch ((uint32_t)env->regs[R_ECX]) {
- case MSR_IA32_SYSENTER_CS:
- val = env->sysenter_cs;
- break;
- case MSR_IA32_SYSENTER_ESP:
- val = env->sysenter_esp;
- break;
- case MSR_IA32_SYSENTER_EIP:
- val = env->sysenter_eip;
- break;
- case MSR_IA32_APICBASE:
- val = cpu_get_apic_base(x86_env_get_cpu(env)->apic_state);
- break;
- case MSR_EFER:
- val = env->efer;
- break;
- case MSR_STAR:
- val = env->star;
- break;
- case MSR_PAT:
- val = env->pat;
- break;
- case MSR_VM_HSAVE_PA:
- val = env->vm_hsave;
- break;
- case MSR_IA32_PERF_STATUS:
- /* tsc_increment_by_tick */
- val = 1000ULL;
- /* CPU multiplier */
- val |= (((uint64_t)4ULL) << 40);
- break;
-#ifdef TARGET_X86_64
- case MSR_LSTAR:
- val = env->lstar;
- break;
- case MSR_CSTAR:
- val = env->cstar;
- break;
- case MSR_FMASK:
- val = env->fmask;
- break;
- case MSR_FSBASE:
- val = env->segs[R_FS].base;
- break;
- case MSR_GSBASE:
- val = env->segs[R_GS].base;
- break;
- case MSR_KERNELGSBASE:
- val = env->kernelgsbase;
- break;
- case MSR_TSC_AUX:
- val = env->tsc_aux;
- break;
-#endif
- case MSR_MTRRphysBase(0):
- case MSR_MTRRphysBase(1):
- case MSR_MTRRphysBase(2):
- case MSR_MTRRphysBase(3):
- case MSR_MTRRphysBase(4):
- case MSR_MTRRphysBase(5):
- case MSR_MTRRphysBase(6):
- case MSR_MTRRphysBase(7):
- val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
- MSR_MTRRphysBase(0)) / 2].base;
- break;
- case MSR_MTRRphysMask(0):
- case MSR_MTRRphysMask(1):
- case MSR_MTRRphysMask(2):
- case MSR_MTRRphysMask(3):
- case MSR_MTRRphysMask(4):
- case MSR_MTRRphysMask(5):
- case MSR_MTRRphysMask(6):
- case MSR_MTRRphysMask(7):
- val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
- MSR_MTRRphysMask(0)) / 2].mask;
- break;
- case MSR_MTRRfix64K_00000:
- val = env->mtrr_fixed[0];
- break;
- case MSR_MTRRfix16K_80000:
- case MSR_MTRRfix16K_A0000:
- val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
- MSR_MTRRfix16K_80000 + 1];
- break;
- case MSR_MTRRfix4K_C0000:
- case MSR_MTRRfix4K_C8000:
- case MSR_MTRRfix4K_D0000:
- case MSR_MTRRfix4K_D8000:
- case MSR_MTRRfix4K_E0000:
- case MSR_MTRRfix4K_E8000:
- case MSR_MTRRfix4K_F0000:
- case MSR_MTRRfix4K_F8000:
- val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
- MSR_MTRRfix4K_C0000 + 3];
- break;
- case MSR_MTRRdefType:
- val = env->mtrr_deftype;
- break;
- case MSR_MTRRcap:
- if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
- val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
- MSR_MTRRcap_WC_SUPPORTED;
- } else {
- /* XXX: exception? */
- val = 0;
- }
- break;
- case MSR_MCG_CAP:
- val = env->mcg_cap;
- break;
- case MSR_MCG_CTL:
- if (env->mcg_cap & MCG_CTL_P) {
- val = env->mcg_ctl;
- } else {
- val = 0;
- }
- break;
- case MSR_MCG_STATUS:
- val = env->mcg_status;
- break;
- case MSR_IA32_MISC_ENABLE:
- val = env->msr_ia32_misc_enable;
- break;
- case MSR_IA32_BNDCFGS:
- val = env->msr_bndcfgs;
- break;
- default:
- if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
- && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
- (4 * env->mcg_cap & 0xff)) {
- uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
- val = env->mce_banks[offset];
- break;
- }
- /* XXX: exception? */
- val = 0;
- break;
- }
- env->regs[R_EAX] = (uint32_t)(val);
- env->regs[R_EDX] = (uint32_t)(val >> 32);
-}
-#endif
-
-static void do_pause(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
-
- /* Just let another CPU run. */
- cs->exception_index = EXCP_INTERRUPT;
- cpu_loop_exit(cs);
-}
-
-static void do_hlt(X86CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
-
- env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
- cs->halted = 1;
- cs->exception_index = EXCP_HLT;
- cpu_loop_exit(cs);
-}
-
-void helper_hlt(CPUX86State *env, int next_eip_addend)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
- env->eip += next_eip_addend;
-
- do_hlt(cpu);
-}
-
-void helper_monitor(CPUX86State *env, target_ulong ptr)
-{
- if ((uint32_t)env->regs[R_ECX] != 0) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
- /* XXX: store address? */
- cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
-}
-
-void helper_mwait(CPUX86State *env, int next_eip_addend)
-{
- CPUState *cs;
- X86CPU *cpu;
-
- if ((uint32_t)env->regs[R_ECX] != 0) {
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
- }
- cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
- env->eip += next_eip_addend;
-
- cpu = x86_env_get_cpu(env);
- cs = CPU(cpu);
- /* XXX: not complete but not completely erroneous */
- if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
- do_pause(cpu);
- } else {
- do_hlt(cpu);
- }
-}
-
-void helper_pause(CPUX86State *env, int next_eip_addend)
-{
- X86CPU *cpu = x86_env_get_cpu(env);
-
- cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
- env->eip += next_eip_addend;
-
- do_pause(cpu);
-}
-
-void helper_debug(CPUX86State *env)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
-
- cs->exception_index = EXCP_DEBUG;
- cpu_loop_exit(cs);
-}
-
-uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
-{
- if ((env->cr[4] & CR4_PKE_MASK) == 0) {
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
- }
- if (ecx != 0) {
- raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
- }
-
- return env->pkru;
-}
-
-void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
-
- if ((env->cr[4] & CR4_PKE_MASK) == 0) {
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
- }
- if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
- raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
- }
-
- env->pkru = val;
- tlb_flush(cs, 1);
-}
diff --git a/target-i386/monitor.c b/target-i386/monitor.c
deleted file mode 100644
index 9a3b4d746e..0000000000
--- a/target-i386/monitor.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * QEMU monitor
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "monitor/monitor.h"
-#include "monitor/hmp-target.h"
-#include "hw/i386/pc.h"
-#include "sysemu/kvm.h"
-#include "hmp.h"
-
-
-static void print_pte(Monitor *mon, hwaddr addr,
- hwaddr pte,
- hwaddr mask)
-{
-#ifdef TARGET_X86_64
- if (addr & (1ULL << 47)) {
- addr |= -1LL << 48;
- }
-#endif
- monitor_printf(mon, TARGET_FMT_plx ": " TARGET_FMT_plx
- " %c%c%c%c%c%c%c%c%c\n",
- addr,
- pte & mask,
- pte & PG_NX_MASK ? 'X' : '-',
- pte & PG_GLOBAL_MASK ? 'G' : '-',
- pte & PG_PSE_MASK ? 'P' : '-',
- pte & PG_DIRTY_MASK ? 'D' : '-',
- pte & PG_ACCESSED_MASK ? 'A' : '-',
- pte & PG_PCD_MASK ? 'C' : '-',
- pte & PG_PWT_MASK ? 'T' : '-',
- pte & PG_USER_MASK ? 'U' : '-',
- pte & PG_RW_MASK ? 'W' : '-');
-}
-
-static void tlb_info_32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2;
- uint32_t pgd, pde, pte;
-
- pgd = env->cr[3] & ~0xfff;
- for(l1 = 0; l1 < 1024; l1++) {
- cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
- pde = le32_to_cpu(pde);
- if (pde & PG_PRESENT_MASK) {
- if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
- /* 4M pages */
- print_pte(mon, (l1 << 22), pde, ~((1 << 21) - 1));
- } else {
- for(l2 = 0; l2 < 1024; l2++) {
- cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
- pte = le32_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, (l1 << 22) + (l2 << 12),
- pte & ~PG_PSE_MASK,
- ~0xfff);
- }
- }
- }
- }
- }
-}
-
-static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2, l3;
- uint64_t pdpe, pde, pte;
- uint64_t pdp_addr, pd_addr, pt_addr;
-
- pdp_addr = env->cr[3] & ~0x1f;
- for (l1 = 0; l1 < 4; l1++) {
- cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- if (pdpe & PG_PRESENT_MASK) {
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- if (pde & PG_PRESENT_MASK) {
- if (pde & PG_PSE_MASK) {
- /* 2M pages with PAE, CR4.PSE is ignored */
- print_pte(mon, (l1 << 30 ) + (l2 << 21), pde,
- ~((hwaddr)(1 << 20) - 1));
- } else {
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
- pte = le64_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, (l1 << 30 ) + (l2 << 21)
- + (l3 << 12),
- pte & ~PG_PSE_MASK,
- ~(hwaddr)0xfff);
- }
- }
- }
- }
- }
- }
- }
-}
-
-#ifdef TARGET_X86_64
-static void tlb_info_64(Monitor *mon, CPUArchState *env)
-{
- uint64_t l1, l2, l3, l4;
- uint64_t pml4e, pdpe, pde, pte;
- uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr;
-
- pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
- for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
- if (pml4e & PG_PRESENT_MASK) {
- pdp_addr = pml4e & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- if (pdpe & PG_PRESENT_MASK) {
- if (pdpe & PG_PSE_MASK) {
- /* 1G pages, CR4.PSE is ignored */
- print_pte(mon, (l1 << 39) + (l2 << 30), pdpe,
- 0x3ffffc0000000ULL);
- } else {
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- if (pde & PG_PRESENT_MASK) {
- if (pde & PG_PSE_MASK) {
- /* 2M pages, CR4.PSE is ignored */
- print_pte(mon, (l1 << 39) + (l2 << 30) +
- (l3 << 21), pde,
- 0x3ffffffe00000ULL);
- } else {
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
- pte = le64_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, (l1 << 39) +
- (l2 << 30) +
- (l3 << 21) + (l4 << 12),
- pte & ~PG_PSE_MASK,
- 0x3fffffffff000ULL);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
-#endif /* TARGET_X86_64 */
-
-void hmp_info_tlb(Monitor *mon, const QDict *qdict)
-{
- CPUArchState *env;
-
- env = mon_get_cpu_env();
-
- if (!(env->cr[0] & CR0_PG_MASK)) {
- monitor_printf(mon, "PG disabled\n");
- return;
- }
- if (env->cr[4] & CR4_PAE_MASK) {
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- tlb_info_64(mon, env);
- } else
-#endif
- {
- tlb_info_pae32(mon, env);
- }
- } else {
- tlb_info_32(mon, env);
- }
-}
-
-static void mem_print(Monitor *mon, hwaddr *pstart,
- int *plast_prot,
- hwaddr end, int prot)
-{
- int prot1;
- prot1 = *plast_prot;
- if (prot != prot1) {
- if (*pstart != -1) {
- monitor_printf(mon, TARGET_FMT_plx "-" TARGET_FMT_plx " "
- TARGET_FMT_plx " %c%c%c\n",
- *pstart, end, end - *pstart,
- prot1 & PG_USER_MASK ? 'u' : '-',
- 'r',
- prot1 & PG_RW_MASK ? 'w' : '-');
- }
- if (prot != 0)
- *pstart = end;
- else
- *pstart = -1;
- *plast_prot = prot;
- }
-}
-
-static void mem_info_32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2;
- int prot, last_prot;
- uint32_t pgd, pde, pte;
- hwaddr start, end;
-
- pgd = env->cr[3] & ~0xfff;
- last_prot = 0;
- start = -1;
- for(l1 = 0; l1 < 1024; l1++) {
- cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
- pde = le32_to_cpu(pde);
- end = l1 << 22;
- if (pde & PG_PRESENT_MASK) {
- if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
- prot = pde & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
- mem_print(mon, &start, &last_prot, end, prot);
- } else {
- for(l2 = 0; l2 < 1024; l2++) {
- cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
- pte = le32_to_cpu(pte);
- end = (l1 << 22) + (l2 << 12);
- if (pte & PG_PRESENT_MASK) {
- prot = pte & pde &
- (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
- } else {
- prot = 0;
- }
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- /* Flush last range */
- mem_print(mon, &start, &last_prot, (hwaddr)1 << 32, 0);
-}
-
-static void mem_info_pae32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2, l3;
- int prot, last_prot;
- uint64_t pdpe, pde, pte;
- uint64_t pdp_addr, pd_addr, pt_addr;
- hwaddr start, end;
-
- pdp_addr = env->cr[3] & ~0x1f;
- last_prot = 0;
- start = -1;
- for (l1 = 0; l1 < 4; l1++) {
- cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- end = l1 << 30;
- if (pdpe & PG_PRESENT_MASK) {
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- end = (l1 << 30) + (l2 << 21);
- if (pde & PG_PRESENT_MASK) {
- if (pde & PG_PSE_MASK) {
- prot = pde & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
- mem_print(mon, &start, &last_prot, end, prot);
- } else {
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
- pte = le64_to_cpu(pte);
- end = (l1 << 30) + (l2 << 21) + (l3 << 12);
- if (pte & PG_PRESENT_MASK) {
- prot = pte & pde & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
- } else {
- prot = 0;
- }
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- /* Flush last range */
- mem_print(mon, &start, &last_prot, (hwaddr)1 << 32, 0);
-}
-
-
-#ifdef TARGET_X86_64
-static void mem_info_64(Monitor *mon, CPUArchState *env)
-{
- int prot, last_prot;
- uint64_t l1, l2, l3, l4;
- uint64_t pml4e, pdpe, pde, pte;
- uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
-
- pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
- last_prot = 0;
- start = -1;
- for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
- end = l1 << 39;
- if (pml4e & PG_PRESENT_MASK) {
- pdp_addr = pml4e & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- end = (l1 << 39) + (l2 << 30);
- if (pdpe & PG_PRESENT_MASK) {
- if (pdpe & PG_PSE_MASK) {
- prot = pdpe & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
- prot &= pml4e;
- mem_print(mon, &start, &last_prot, end, prot);
- } else {
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- end = (l1 << 39) + (l2 << 30) + (l3 << 21);
- if (pde & PG_PRESENT_MASK) {
- if (pde & PG_PSE_MASK) {
- prot = pde & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
- prot &= pml4e & pdpe;
- mem_print(mon, &start, &last_prot, end, prot);
- } else {
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
- pte = le64_to_cpu(pte);
- end = (l1 << 39) + (l2 << 30) +
- (l3 << 21) + (l4 << 12);
- if (pte & PG_PRESENT_MASK) {
- prot = pte & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
- prot &= pml4e & pdpe & pde;
- } else {
- prot = 0;
- }
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- } else {
- prot = 0;
- mem_print(mon, &start, &last_prot, end, prot);
- }
- }
- /* Flush last range */
- mem_print(mon, &start, &last_prot, (hwaddr)1 << 48, 0);
-}
-#endif /* TARGET_X86_64 */
-
-void hmp_info_mem(Monitor *mon, const QDict *qdict)
-{
- CPUArchState *env;
-
- env = mon_get_cpu_env();
-
- if (!(env->cr[0] & CR0_PG_MASK)) {
- monitor_printf(mon, "PG disabled\n");
- return;
- }
- if (env->cr[4] & CR4_PAE_MASK) {
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- mem_info_64(mon, env);
- } else
-#endif
- {
- mem_info_pae32(mon, env);
- }
- } else {
- mem_info_32(mon, env);
- }
-}
-
-void hmp_mce(Monitor *mon, const QDict *qdict)
-{
- X86CPU *cpu;
- CPUState *cs;
- int cpu_index = qdict_get_int(qdict, "cpu_index");
- int bank = qdict_get_int(qdict, "bank");
- uint64_t status = qdict_get_int(qdict, "status");
- uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
- uint64_t addr = qdict_get_int(qdict, "addr");
- uint64_t misc = qdict_get_int(qdict, "misc");
- int flags = MCE_INJECT_UNCOND_AO;
-
- if (qdict_get_try_bool(qdict, "broadcast", false)) {
- flags |= MCE_INJECT_BROADCAST;
- }
- cs = qemu_get_cpu(cpu_index);
- if (cs != NULL) {
- cpu = X86_CPU(cs);
- cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
- flags);
- }
-}
-
-static target_long monitor_get_pc(const struct MonitorDef *md, int val)
-{
- CPUArchState *env = mon_get_cpu_env();
- return env->eip + env->segs[R_CS].base;
-}
-
-const MonitorDef monitor_defs[] = {
-#define SEG(name, seg) \
- { name, offsetof(CPUX86State, segs[seg].selector), NULL, MD_I32 },\
- { name ".base", offsetof(CPUX86State, segs[seg].base) },\
- { name ".limit", offsetof(CPUX86State, segs[seg].limit), NULL, MD_I32 },
-
- { "eax", offsetof(CPUX86State, regs[0]) },
- { "ecx", offsetof(CPUX86State, regs[1]) },
- { "edx", offsetof(CPUX86State, regs[2]) },
- { "ebx", offsetof(CPUX86State, regs[3]) },
- { "esp|sp", offsetof(CPUX86State, regs[4]) },
- { "ebp|fp", offsetof(CPUX86State, regs[5]) },
- { "esi", offsetof(CPUX86State, regs[6]) },
- { "edi", offsetof(CPUX86State, regs[7]) },
-#ifdef TARGET_X86_64
- { "r8", offsetof(CPUX86State, regs[8]) },
- { "r9", offsetof(CPUX86State, regs[9]) },
- { "r10", offsetof(CPUX86State, regs[10]) },
- { "r11", offsetof(CPUX86State, regs[11]) },
- { "r12", offsetof(CPUX86State, regs[12]) },
- { "r13", offsetof(CPUX86State, regs[13]) },
- { "r14", offsetof(CPUX86State, regs[14]) },
- { "r15", offsetof(CPUX86State, regs[15]) },
-#endif
- { "eflags", offsetof(CPUX86State, eflags) },
- { "eip", offsetof(CPUX86State, eip) },
- SEG("cs", R_CS)
- SEG("ds", R_DS)
- SEG("es", R_ES)
- SEG("ss", R_SS)
- SEG("fs", R_FS)
- SEG("gs", R_GS)
- { "pc", 0, monitor_get_pc, },
- { NULL },
-};
-
-const MonitorDef *target_monitor_defs(void)
-{
- return monitor_defs;
-}
-
-void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
-{
- x86_cpu_dump_local_apic_state(mon_get_cpu(), (FILE *)mon, monitor_fprintf,
- CPU_DUMP_FPU);
-}
-
-void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
-{
- if (kvm_irqchip_in_kernel() &&
- !kvm_irqchip_is_split()) {
- kvm_ioapic_dump_state(mon, qdict);
- } else {
- ioapic_dump_state(mon, qdict);
- }
-}
diff --git a/target-i386/mpx_helper.c b/target-i386/mpx_helper.c
deleted file mode 100644
index 7e44820659..0000000000
--- a/target-i386/mpx_helper.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * x86 MPX helpers
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * 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 "cpu.h"
-#include "exec/helper-proto.h"
-#include "exec/cpu_ldst.h"
-#include "exec/exec-all.h"
-
-
-void cpu_sync_bndcs_hflags(CPUX86State *env)
-{
- uint32_t hflags = env->hflags;
- uint32_t hflags2 = env->hflags2;
- uint32_t bndcsr;
-
- if ((hflags & HF_CPL_MASK) == 3) {
- bndcsr = env->bndcs_regs.cfgu;
- } else {
- bndcsr = env->msr_bndcfgs;
- }
-
- if ((env->cr[4] & CR4_OSXSAVE_MASK)
- && (env->xcr0 & XSTATE_BNDCSR_MASK)
- && (bndcsr & BNDCFG_ENABLE)) {
- hflags |= HF_MPX_EN_MASK;
- } else {
- hflags &= ~HF_MPX_EN_MASK;
- }
-
- if (bndcsr & BNDCFG_BNDPRESERVE) {
- hflags2 |= HF2_MPX_PR_MASK;
- } else {
- hflags2 &= ~HF2_MPX_PR_MASK;
- }
-
- env->hflags = hflags;
- env->hflags2 = hflags2;
-}
-
-void helper_bndck(CPUX86State *env, uint32_t fail)
-{
- if (unlikely(fail)) {
- env->bndcs_regs.sts = 1;
- raise_exception_ra(env, EXCP05_BOUND, GETPC());
- }
-}
-
-static uint64_t lookup_bte64(CPUX86State *env, uint64_t base, uintptr_t ra)
-{
- uint64_t bndcsr, bde, bt;
-
- if ((env->hflags & HF_CPL_MASK) == 3) {
- bndcsr = env->bndcs_regs.cfgu;
- } else {
- bndcsr = env->msr_bndcfgs;
- }
-
- bde = (extract64(base, 20, 28) << 3) + (extract64(bndcsr, 20, 44) << 12);
- bt = cpu_ldq_data_ra(env, bde, ra);
- if ((bt & 1) == 0) {
- env->bndcs_regs.sts = bde | 2;
- raise_exception_ra(env, EXCP05_BOUND, ra);
- }
-
- return (extract64(base, 3, 17) << 5) + (bt & ~7);
-}
-
-static uint32_t lookup_bte32(CPUX86State *env, uint32_t base, uintptr_t ra)
-{
- uint32_t bndcsr, bde, bt;
-
- if ((env->hflags & HF_CPL_MASK) == 3) {
- bndcsr = env->bndcs_regs.cfgu;
- } else {
- bndcsr = env->msr_bndcfgs;
- }
-
- bde = (extract32(base, 12, 20) << 2) + (bndcsr & TARGET_PAGE_MASK);
- bt = cpu_ldl_data_ra(env, bde, ra);
- if ((bt & 1) == 0) {
- env->bndcs_regs.sts = bde | 2;
- raise_exception_ra(env, EXCP05_BOUND, ra);
- }
-
- return (extract32(base, 2, 10) << 4) + (bt & ~3);
-}
-
-uint64_t helper_bndldx64(CPUX86State *env, target_ulong base, target_ulong ptr)
-{
- uintptr_t ra = GETPC();
- uint64_t bte, lb, ub, pt;
-
- bte = lookup_bte64(env, base, ra);
- lb = cpu_ldq_data_ra(env, bte, ra);
- ub = cpu_ldq_data_ra(env, bte + 8, ra);
- pt = cpu_ldq_data_ra(env, bte + 16, ra);
-
- if (pt != ptr) {
- lb = ub = 0;
- }
- env->mmx_t0.MMX_Q(0) = ub;
- return lb;
-}
-
-uint64_t helper_bndldx32(CPUX86State *env, target_ulong base, target_ulong ptr)
-{
- uintptr_t ra = GETPC();
- uint32_t bte, lb, ub, pt;
-
- bte = lookup_bte32(env, base, ra);
- lb = cpu_ldl_data_ra(env, bte, ra);
- ub = cpu_ldl_data_ra(env, bte + 4, ra);
- pt = cpu_ldl_data_ra(env, bte + 8, ra);
-
- if (pt != ptr) {
- lb = ub = 0;
- }
- return ((uint64_t)ub << 32) | lb;
-}
-
-void helper_bndstx64(CPUX86State *env, target_ulong base, target_ulong ptr,
- uint64_t lb, uint64_t ub)
-{
- uintptr_t ra = GETPC();
- uint64_t bte;
-
- bte = lookup_bte64(env, base, ra);
- cpu_stq_data_ra(env, bte, lb, ra);
- cpu_stq_data_ra(env, bte + 8, ub, ra);
- cpu_stq_data_ra(env, bte + 16, ptr, ra);
-}
-
-void helper_bndstx32(CPUX86State *env, target_ulong base, target_ulong ptr,
- uint64_t lb, uint64_t ub)
-{
- uintptr_t ra = GETPC();
- uint32_t bte;
-
- bte = lookup_bte32(env, base, ra);
- cpu_stl_data_ra(env, bte, lb, ra);
- cpu_stl_data_ra(env, bte + 4, ub, ra);
- cpu_stl_data_ra(env, bte + 8, ptr, ra);
-}
-
-void helper_bnd_jmp(CPUX86State *env)
-{
- if (!(env->hflags2 & HF2_MPX_PR_MASK)) {
- memset(env->bnd_regs, 0, sizeof(env->bnd_regs));
- env->hflags &= ~HF_MPX_IU_MASK;
- }
-}
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
deleted file mode 100644
index 7a98f53864..0000000000
--- a/target-i386/ops_sse.h
+++ /dev/null
@@ -1,2296 +0,0 @@
-/*
- * MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI support
- *
- * Copyright (c) 2005 Fabrice Bellard
- * Copyright (c) 2008 Intel Corporation <andrew.zaborowski@intel.com>
- *
- * 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 "crypto/aes.h"
-
-#if SHIFT == 0
-#define Reg MMXReg
-#define XMM_ONLY(...)
-#define B(n) MMX_B(n)
-#define W(n) MMX_W(n)
-#define L(n) MMX_L(n)
-#define Q(n) MMX_Q(n)
-#define SUFFIX _mmx
-#else
-#define Reg ZMMReg
-#define XMM_ONLY(...) __VA_ARGS__
-#define B(n) ZMM_B(n)
-#define W(n) ZMM_W(n)
-#define L(n) ZMM_L(n)
-#define Q(n) ZMM_Q(n)
-#define SUFFIX _xmm
-#endif
-
-void glue(helper_psrlw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 15) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->W(0) >>= shift;
- d->W(1) >>= shift;
- d->W(2) >>= shift;
- d->W(3) >>= shift;
-#if SHIFT == 1
- d->W(4) >>= shift;
- d->W(5) >>= shift;
- d->W(6) >>= shift;
- d->W(7) >>= shift;
-#endif
- }
-}
-
-void glue(helper_psraw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 15) {
- shift = 15;
- } else {
- shift = s->B(0);
- }
- d->W(0) = (int16_t)d->W(0) >> shift;
- d->W(1) = (int16_t)d->W(1) >> shift;
- d->W(2) = (int16_t)d->W(2) >> shift;
- d->W(3) = (int16_t)d->W(3) >> shift;
-#if SHIFT == 1
- d->W(4) = (int16_t)d->W(4) >> shift;
- d->W(5) = (int16_t)d->W(5) >> shift;
- d->W(6) = (int16_t)d->W(6) >> shift;
- d->W(7) = (int16_t)d->W(7) >> shift;
-#endif
-}
-
-void glue(helper_psllw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 15) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->W(0) <<= shift;
- d->W(1) <<= shift;
- d->W(2) <<= shift;
- d->W(3) <<= shift;
-#if SHIFT == 1
- d->W(4) <<= shift;
- d->W(5) <<= shift;
- d->W(6) <<= shift;
- d->W(7) <<= shift;
-#endif
- }
-}
-
-void glue(helper_psrld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 31) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->L(0) >>= shift;
- d->L(1) >>= shift;
-#if SHIFT == 1
- d->L(2) >>= shift;
- d->L(3) >>= shift;
-#endif
- }
-}
-
-void glue(helper_psrad, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 31) {
- shift = 31;
- } else {
- shift = s->B(0);
- }
- d->L(0) = (int32_t)d->L(0) >> shift;
- d->L(1) = (int32_t)d->L(1) >> shift;
-#if SHIFT == 1
- d->L(2) = (int32_t)d->L(2) >> shift;
- d->L(3) = (int32_t)d->L(3) >> shift;
-#endif
-}
-
-void glue(helper_pslld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 31) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->L(0) <<= shift;
- d->L(1) <<= shift;
-#if SHIFT == 1
- d->L(2) <<= shift;
- d->L(3) <<= shift;
-#endif
- }
-}
-
-void glue(helper_psrlq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 63) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->Q(0) >>= shift;
-#if SHIFT == 1
- d->Q(1) >>= shift;
-#endif
- }
-}
-
-void glue(helper_psllq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift;
-
- if (s->Q(0) > 63) {
- d->Q(0) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
- } else {
- shift = s->B(0);
- d->Q(0) <<= shift;
-#if SHIFT == 1
- d->Q(1) <<= shift;
-#endif
- }
-}
-
-#if SHIFT == 1
-void glue(helper_psrldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift, i;
-
- shift = s->L(0);
- if (shift > 16) {
- shift = 16;
- }
- for (i = 0; i < 16 - shift; i++) {
- d->B(i) = d->B(i + shift);
- }
- for (i = 16 - shift; i < 16; i++) {
- d->B(i) = 0;
- }
-}
-
-void glue(helper_pslldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int shift, i;
-
- shift = s->L(0);
- if (shift > 16) {
- shift = 16;
- }
- for (i = 15; i >= shift; i--) {
- d->B(i) = d->B(i - shift);
- }
- for (i = 0; i < shift; i++) {
- d->B(i) = 0;
- }
-}
-#endif
-
-#define SSE_HELPER_B(name, F) \
- void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \
- { \
- d->B(0) = F(d->B(0), s->B(0)); \
- d->B(1) = F(d->B(1), s->B(1)); \
- d->B(2) = F(d->B(2), s->B(2)); \
- d->B(3) = F(d->B(3), s->B(3)); \
- d->B(4) = F(d->B(4), s->B(4)); \
- d->B(5) = F(d->B(5), s->B(5)); \
- d->B(6) = F(d->B(6), s->B(6)); \
- d->B(7) = F(d->B(7), s->B(7)); \
- XMM_ONLY( \
- d->B(8) = F(d->B(8), s->B(8)); \
- d->B(9) = F(d->B(9), s->B(9)); \
- d->B(10) = F(d->B(10), s->B(10)); \
- d->B(11) = F(d->B(11), s->B(11)); \
- d->B(12) = F(d->B(12), s->B(12)); \
- d->B(13) = F(d->B(13), s->B(13)); \
- d->B(14) = F(d->B(14), s->B(14)); \
- d->B(15) = F(d->B(15), s->B(15)); \
- ) \
- }
-
-#define SSE_HELPER_W(name, F) \
- void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \
- { \
- d->W(0) = F(d->W(0), s->W(0)); \
- d->W(1) = F(d->W(1), s->W(1)); \
- d->W(2) = F(d->W(2), s->W(2)); \
- d->W(3) = F(d->W(3), s->W(3)); \
- XMM_ONLY( \
- d->W(4) = F(d->W(4), s->W(4)); \
- d->W(5) = F(d->W(5), s->W(5)); \
- d->W(6) = F(d->W(6), s->W(6)); \
- d->W(7) = F(d->W(7), s->W(7)); \
- ) \
- }
-
-#define SSE_HELPER_L(name, F) \
- void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \
- { \
- d->L(0) = F(d->L(0), s->L(0)); \
- d->L(1) = F(d->L(1), s->L(1)); \
- XMM_ONLY( \
- d->L(2) = F(d->L(2), s->L(2)); \
- d->L(3) = F(d->L(3), s->L(3)); \
- ) \
- }
-
-#define SSE_HELPER_Q(name, F) \
- void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \
- { \
- d->Q(0) = F(d->Q(0), s->Q(0)); \
- XMM_ONLY( \
- d->Q(1) = F(d->Q(1), s->Q(1)); \
- ) \
- }
-
-#if SHIFT == 0
-static inline int satub(int x)
-{
- if (x < 0) {
- return 0;
- } else if (x > 255) {
- return 255;
- } else {
- return x;
- }
-}
-
-static inline int satuw(int x)
-{
- if (x < 0) {
- return 0;
- } else if (x > 65535) {
- return 65535;
- } else {
- return x;
- }
-}
-
-static inline int satsb(int x)
-{
- if (x < -128) {
- return -128;
- } else if (x > 127) {
- return 127;
- } else {
- return x;
- }
-}
-
-static inline int satsw(int x)
-{
- if (x < -32768) {
- return -32768;
- } else if (x > 32767) {
- return 32767;
- } else {
- return x;
- }
-}
-
-#define FADD(a, b) ((a) + (b))
-#define FADDUB(a, b) satub((a) + (b))
-#define FADDUW(a, b) satuw((a) + (b))
-#define FADDSB(a, b) satsb((int8_t)(a) + (int8_t)(b))
-#define FADDSW(a, b) satsw((int16_t)(a) + (int16_t)(b))
-
-#define FSUB(a, b) ((a) - (b))
-#define FSUBUB(a, b) satub((a) - (b))
-#define FSUBUW(a, b) satuw((a) - (b))
-#define FSUBSB(a, b) satsb((int8_t)(a) - (int8_t)(b))
-#define FSUBSW(a, b) satsw((int16_t)(a) - (int16_t)(b))
-#define FMINUB(a, b) ((a) < (b)) ? (a) : (b)
-#define FMINSW(a, b) ((int16_t)(a) < (int16_t)(b)) ? (a) : (b)
-#define FMAXUB(a, b) ((a) > (b)) ? (a) : (b)
-#define FMAXSW(a, b) ((int16_t)(a) > (int16_t)(b)) ? (a) : (b)
-
-#define FAND(a, b) ((a) & (b))
-#define FANDN(a, b) ((~(a)) & (b))
-#define FOR(a, b) ((a) | (b))
-#define FXOR(a, b) ((a) ^ (b))
-
-#define FCMPGTB(a, b) ((int8_t)(a) > (int8_t)(b) ? -1 : 0)
-#define FCMPGTW(a, b) ((int16_t)(a) > (int16_t)(b) ? -1 : 0)
-#define FCMPGTL(a, b) ((int32_t)(a) > (int32_t)(b) ? -1 : 0)
-#define FCMPEQ(a, b) ((a) == (b) ? -1 : 0)
-
-#define FMULLW(a, b) ((a) * (b))
-#define FMULHRW(a, b) (((int16_t)(a) * (int16_t)(b) + 0x8000) >> 16)
-#define FMULHUW(a, b) ((a) * (b) >> 16)
-#define FMULHW(a, b) ((int16_t)(a) * (int16_t)(b) >> 16)
-
-#define FAVG(a, b) (((a) + (b) + 1) >> 1)
-#endif
-
-SSE_HELPER_B(helper_paddb, FADD)
-SSE_HELPER_W(helper_paddw, FADD)
-SSE_HELPER_L(helper_paddl, FADD)
-SSE_HELPER_Q(helper_paddq, FADD)
-
-SSE_HELPER_B(helper_psubb, FSUB)
-SSE_HELPER_W(helper_psubw, FSUB)
-SSE_HELPER_L(helper_psubl, FSUB)
-SSE_HELPER_Q(helper_psubq, FSUB)
-
-SSE_HELPER_B(helper_paddusb, FADDUB)
-SSE_HELPER_B(helper_paddsb, FADDSB)
-SSE_HELPER_B(helper_psubusb, FSUBUB)
-SSE_HELPER_B(helper_psubsb, FSUBSB)
-
-SSE_HELPER_W(helper_paddusw, FADDUW)
-SSE_HELPER_W(helper_paddsw, FADDSW)
-SSE_HELPER_W(helper_psubusw, FSUBUW)
-SSE_HELPER_W(helper_psubsw, FSUBSW)
-
-SSE_HELPER_B(helper_pminub, FMINUB)
-SSE_HELPER_B(helper_pmaxub, FMAXUB)
-
-SSE_HELPER_W(helper_pminsw, FMINSW)
-SSE_HELPER_W(helper_pmaxsw, FMAXSW)
-
-SSE_HELPER_Q(helper_pand, FAND)
-SSE_HELPER_Q(helper_pandn, FANDN)
-SSE_HELPER_Q(helper_por, FOR)
-SSE_HELPER_Q(helper_pxor, FXOR)
-
-SSE_HELPER_B(helper_pcmpgtb, FCMPGTB)
-SSE_HELPER_W(helper_pcmpgtw, FCMPGTW)
-SSE_HELPER_L(helper_pcmpgtl, FCMPGTL)
-
-SSE_HELPER_B(helper_pcmpeqb, FCMPEQ)
-SSE_HELPER_W(helper_pcmpeqw, FCMPEQ)
-SSE_HELPER_L(helper_pcmpeql, FCMPEQ)
-
-SSE_HELPER_W(helper_pmullw, FMULLW)
-#if SHIFT == 0
-SSE_HELPER_W(helper_pmulhrw, FMULHRW)
-#endif
-SSE_HELPER_W(helper_pmulhuw, FMULHUW)
-SSE_HELPER_W(helper_pmulhw, FMULHW)
-
-SSE_HELPER_B(helper_pavgb, FAVG)
-SSE_HELPER_W(helper_pavgw, FAVG)
-
-void glue(helper_pmuludq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- d->Q(0) = (uint64_t)s->L(0) * (uint64_t)d->L(0);
-#if SHIFT == 1
- d->Q(1) = (uint64_t)s->L(2) * (uint64_t)d->L(2);
-#endif
-}
-
-void glue(helper_pmaddwd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- int i;
-
- for (i = 0; i < (2 << SHIFT); i++) {
- d->L(i) = (int16_t)s->W(2 * i) * (int16_t)d->W(2 * i) +
- (int16_t)s->W(2 * i + 1) * (int16_t)d->W(2 * i + 1);
- }
-}
-
-#if SHIFT == 0
-static inline int abs1(int a)
-{
- if (a < 0) {
- return -a;
- } else {
- return a;
- }
-}
-#endif
-void glue(helper_psadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
- unsigned int val;
-
- val = 0;
- val += abs1(d->B(0) - s->B(0));
- val += abs1(d->B(1) - s->B(1));
- val += abs1(d->B(2) - s->B(2));
- val += abs1(d->B(3) - s->B(3));
- val += abs1(d->B(4) - s->B(4));
- val += abs1(d->B(5) - s->B(5));
- val += abs1(d->B(6) - s->B(6));
- val += abs1(d->B(7) - s->B(7));
- d->Q(0) = val;
-#if SHIFT == 1
- val = 0;
- val += abs1(d->B(8) - s->B(8));
- val += abs1(d->B(9) - s->B(9));
- val += abs1(d->B(10) - s->B(10));
- val += abs1(d->B(11) - s->B(11));
- val += abs1(d->B(12) - s->B(12));
- val += abs1(d->B(13) - s->B(13));
- val += abs1(d->B(14) - s->B(14));
- val += abs1(d->B(15) - s->B(15));
- d->Q(1) = val;
-#endif
-}
-
-void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
- target_ulong a0)
-{
- int i;
-
- for (i = 0; i < (8 << SHIFT); i++) {
- if (s->B(i) & 0x80) {
- cpu_stb_data_ra(env, a0 + i, d->B(i), GETPC());
- }
- }
-}
-
-void glue(helper_movl_mm_T0, SUFFIX)(Reg *d, uint32_t val)
-{
- d->L(0) = val;
- d->L(1) = 0;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
-}
-
-#ifdef TARGET_X86_64
-void glue(helper_movq_mm_T0, SUFFIX)(Reg *d, uint64_t val)
-{
- d->Q(0) = val;
-#if SHIFT == 1
- d->Q(1) = 0;
-#endif
-}
-#endif
-
-#if SHIFT == 0
-void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *s, int order)
-{
- Reg r;
-
- r.W(0) = s->W(order & 3);
- r.W(1) = s->W((order >> 2) & 3);
- r.W(2) = s->W((order >> 4) & 3);
- r.W(3) = s->W((order >&g