* Fixes for "-cpu max" on i386 TCG (Daniel)
* vVMLOAD/VMSAVE and vGIF implementation (Lara) * Reorganize i386 targets documentation in preparation for SGX (myself) * Meson cleanups (myself, Thomas) * NVMM fixes (Reinoud) * Suppress bogus -Wstringop-overflow (Richard) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmE/PHEUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroNn0ggAhOApMUZR2L9p4Z56X+Nnc1835dOJ QlX8UmMpoRBPuIKfaJPJQWwYeRSw4Nqaik3EndXug8Mo3LJaG5AFEHTXDkZGHMgh tGCyeARhDnUQPfKLszT1zg0EMloX6bCLFaA9ba1JBNK8VWXE4oJJLETk3Q+pDJZt 0ztoxaLvQ2jaMFfPKtLdyhcXjDCPeZZjaQjCFVVmWV9hj8z4np3LZLoYi8a6cRWu u1Rb5SrftF12tu+RWACXZFQSnxFkU+iVeoKhQB0vrh7UgV/HAAbZS8c2U46v/kM0 H6UcuBPjrz3fF/9hHNdovb4HxyQAP2pEliBSG7tFzJ+TbnMQVcoxN5uJ2Q== =DBxg -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging * Fixes for "-cpu max" on i386 TCG (Daniel) * vVMLOAD/VMSAVE and vGIF implementation (Lara) * Reorganize i386 targets documentation in preparation for SGX (myself) * Meson cleanups (myself, Thomas) * NVMM fixes (Reinoud) * Suppress bogus -Wstringop-overflow (Richard) # gpg: Signature made Mon 13 Sep 2021 12:56:33 BST # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini-gitlab/tags/for-upstream: (21 commits) docs: link to archived Fedora code of conduct Fix nvmm_ram_block_added() function arguments Only check CONFIG_NVMM when NEED_CPU_H is defined util: Suppress -Wstringop-overflow in qemu_thread_start fw_cfg: add etc/msr_feature_control meson: remove dead variable meson: do not use python.full_path() unnecessarily meson: look up cp and dtrace with find_program() meson.build: Do not look for VNC-related libraries if have_system is not set docs/system: move x86 CPU configuration to a separate document docs/system: standardize man page sections to --- with overline docs: standardize directory index to --- with overline docs: standardize book titles to === with overline target/i386: Added vVMLOAD and vVMSAVE feature target/i386: Added changed priority check for VIRQ target/i386: Added ignore TPR check in ctl_has_irq target/i386: Added VGIF V_IRQ masking capability target/i386: Moved int_ctl into CPUX86State structure target/i386: Added VGIF feature target/i386: VMRUN and VMLOAD canonicalizations ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7d79344d4f
@ -1,5 +1,6 @@
|
||||
----------
|
||||
About QEMU
|
||||
==========
|
||||
----------
|
||||
|
||||
QEMU is a generic and open source machine emulator and virtualizer.
|
||||
|
||||
|
@ -55,6 +55,6 @@ Sources
|
||||
-------
|
||||
|
||||
This document is based on the `Fedora Code of Conduct
|
||||
<https://fedoraproject.org/code-of-conduct>`__ and the
|
||||
`Contributor Covenant version 1.3.0
|
||||
<http://web.archive.org/web/20210429132536/https://docs.fedoraproject.org/en-US/project/code-of-conduct/>`__
|
||||
(as of April 2021) and the `Contributor Covenant version 1.3.0
|
||||
<https://www.contributor-covenant.org/version/1/3/0/code-of-conduct/>`__.
|
||||
|
@ -1,5 +1,6 @@
|
||||
---------------------
|
||||
Developer Information
|
||||
=====================
|
||||
---------------------
|
||||
|
||||
This section of the manual documents various parts of the internals of QEMU.
|
||||
You only need to read it if you are interested in reading or
|
||||
|
@ -3,6 +3,7 @@
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
================================
|
||||
Welcome to QEMU's documentation!
|
||||
================================
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
------------------------------------------------
|
||||
System Emulation Management and Interoperability
|
||||
================================================
|
||||
------------------------------------------------
|
||||
|
||||
This section of the manual contains documents and specifications that
|
||||
are useful for making QEMU interoperate with other software.
|
||||
|
@ -1,5 +1,6 @@
|
||||
----------------------------------------------
|
||||
System Emulation Guest Hardware Specifications
|
||||
==============================================
|
||||
----------------------------------------------
|
||||
|
||||
This section of the manual contains specifications of
|
||||
guest hardware that is specific to QEMU.
|
||||
|
@ -1,5 +1,5 @@
|
||||
Recommendations for KVM CPU model configuration on x86 hosts
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
============================================================
|
||||
|
||||
The information that follows provides recommendations for configuring
|
||||
CPU models on x86 hosts. The goals are to maximise performance, while
|
||||
@ -368,7 +368,7 @@ featureset, which prevents guests having optimal performance.
|
||||
|
||||
|
||||
Syntax for configuring CPU models
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
=================================
|
||||
|
||||
The examples below illustrate the approach to configuring the various
|
||||
CPU models / features in QEMU and libvirt.
|
||||
|
1
docs/system/i386/cpu.rst
Normal file
1
docs/system/i386/cpu.rst
Normal file
@ -0,0 +1 @@
|
||||
.. include:: ../cpu-models-x86.rst.inc
|
@ -1,5 +1,6 @@
|
||||
----------------
|
||||
System Emulation
|
||||
================
|
||||
----------------
|
||||
|
||||
This section of the manual is the overall guide for users using QEMU
|
||||
for full system emulation (as opposed to user-mode emulation).
|
||||
|
@ -1,18 +1,22 @@
|
||||
:orphan:
|
||||
|
||||
============================
|
||||
QEMU block drivers reference
|
||||
============================
|
||||
|
||||
--------
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
QEMU block driver reference manual
|
||||
|
||||
-----------
|
||||
Description
|
||||
-----------
|
||||
|
||||
.. include:: qemu-block-drivers.rst.inc
|
||||
|
||||
--------
|
||||
See also
|
||||
--------
|
||||
|
||||
|
@ -1,20 +1,24 @@
|
||||
:orphan:
|
||||
|
||||
==================================
|
||||
QEMU / KVM CPU model configuration
|
||||
==================================
|
||||
|
||||
--------
|
||||
Synopsis
|
||||
''''''''
|
||||
--------
|
||||
|
||||
QEMU CPU Modelling Infrastructure manual
|
||||
|
||||
-----------
|
||||
Description
|
||||
'''''''''''
|
||||
-----------
|
||||
|
||||
.. include:: cpu-models-x86.rst.inc
|
||||
.. include:: cpu-models-mips.rst.inc
|
||||
|
||||
--------
|
||||
See also
|
||||
''''''''
|
||||
--------
|
||||
|
||||
The HTML documentation of QEMU for more precise information and Linux user mode emulator invocation.
|
||||
|
@ -6,9 +6,11 @@
|
||||
parts of the documentation that go in the manpage as well as the
|
||||
HTML manual.
|
||||
|
||||
Title
|
||||
=====
|
||||
=======================
|
||||
QEMU User Documentation
|
||||
=======================
|
||||
|
||||
--------
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
@ -16,11 +18,13 @@ Synopsis
|
||||
|
||||
|qemu_system| [options] [disk_image]
|
||||
|
||||
-----------
|
||||
Description
|
||||
-----------
|
||||
|
||||
.. include:: target-i386-desc.rst.inc
|
||||
|
||||
-------
|
||||
Options
|
||||
-------
|
||||
|
||||
@ -33,11 +37,13 @@ not need a disk image.
|
||||
|
||||
.. include:: mux-chardev.rst.inc
|
||||
|
||||
-----
|
||||
Notes
|
||||
-----
|
||||
|
||||
.. include:: device-url-syntax.rst.inc
|
||||
|
||||
--------
|
||||
See also
|
||||
--------
|
||||
|
||||
|
@ -19,7 +19,13 @@ Board-specific documentation
|
||||
i386/microvm
|
||||
i386/pc
|
||||
|
||||
.. include:: cpu-models-x86.rst.inc
|
||||
Architectural features
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
i386/cpu
|
||||
|
||||
.. _pcsys_005freq:
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
-----
|
||||
Tools
|
||||
=====
|
||||
-----
|
||||
|
||||
This section of the manual documents QEMU's "tools": its
|
||||
command line utilities and other standalone programs.
|
||||
|
@ -1,3 +1,4 @@
|
||||
=======================
|
||||
QEMU disk image utility
|
||||
=======================
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
=====================================
|
||||
QEMU Disk Network Block Device Server
|
||||
=====================================
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
==================================
|
||||
QEMU persistent reservation helper
|
||||
==================================
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
===================
|
||||
QEMU Storage Daemon
|
||||
===================
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
=========================
|
||||
QEMU SystemTap trace tool
|
||||
=========================
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
-------------------
|
||||
User Mode Emulation
|
||||
===================
|
||||
-------------------
|
||||
|
||||
This section of the manual is the overall guide for users using QEMU
|
||||
for user-mode emulation. In this mode, QEMU can launch
|
||||
|
@ -878,6 +878,7 @@ static struct {
|
||||
{ "etc/tpm/log", 150 },
|
||||
{ "etc/acpi/rsdp", 160 },
|
||||
{ "bootorder", 170 },
|
||||
{ "etc/msr_feature_control", 180 },
|
||||
|
||||
#define FW_CFG_ORDER_OVERRIDE_LAST 200
|
||||
};
|
||||
|
@ -10,8 +10,7 @@
|
||||
#ifndef QEMU_NVMM_H
|
||||
#define QEMU_NVMM_H
|
||||
|
||||
#include "config-host.h"
|
||||
#include "qemu-common.h"
|
||||
#ifdef NEED_CPU_H
|
||||
|
||||
#ifdef CONFIG_NVMM
|
||||
|
||||
@ -23,4 +22,6 @@ int nvmm_enabled(void);
|
||||
|
||||
#endif /* CONFIG_NVMM */
|
||||
|
||||
#endif /* CONFIG_NVMM */
|
||||
#endif /* NEED_CPU_H */
|
||||
|
||||
#endif /* QEMU_NVMM_H */
|
||||
|
@ -931,7 +931,7 @@ vnc = not_found
|
||||
png = not_found
|
||||
jpeg = not_found
|
||||
sasl = not_found
|
||||
if not get_option('vnc').disabled()
|
||||
if have_system and not get_option('vnc').disabled()
|
||||
vnc = declare_dependency() # dummy dependency
|
||||
png = dependency('libpng', required: get_option('vnc_png'),
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
|
@ -38,6 +38,7 @@ if meson.is_cross_build() or 'CONFIG_XKBCOMMON' not in config_host
|
||||
else
|
||||
native_qemu_keymap = qemu_keymap
|
||||
endif
|
||||
cp = find_program('cp')
|
||||
|
||||
t = []
|
||||
foreach km, args: keymaps
|
||||
@ -55,7 +56,7 @@ foreach km, args: keymaps
|
||||
build_by_default: true,
|
||||
input: km,
|
||||
output: km,
|
||||
command: ['cp', '@INPUT@', '@OUTPUT@'],
|
||||
command: [cp, '@INPUT@', '@OUTPUT@'],
|
||||
install: true,
|
||||
install_dir: qemu_datadir / 'keymaps')
|
||||
endif
|
||||
|
@ -631,7 +631,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
||||
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
|
||||
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
|
||||
#define TCG_EXT4_FEATURES 0
|
||||
#define TCG_SVM_FEATURES CPUID_SVM_NPT
|
||||
#define TCG_SVM_FEATURES (CPUID_SVM_NPT | CPUID_SVM_VGIF | \
|
||||
CPUID_SVM_SVME_ADDR_CHK)
|
||||
#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 | \
|
||||
@ -5115,6 +5116,15 @@ static void x86_register_cpudef_types(const X86CPUDefinition *def)
|
||||
|
||||
}
|
||||
|
||||
uint32_t cpu_x86_virtual_addr_width(CPUX86State *env)
|
||||
{
|
||||
if (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57) {
|
||||
return 57; /* 57 bits virtual */
|
||||
} else {
|
||||
return 48; /* 48 bits virtual */
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
uint32_t *eax, uint32_t *ebx,
|
||||
uint32_t *ecx, uint32_t *edx)
|
||||
@ -5517,16 +5527,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
break;
|
||||
case 0x80000008:
|
||||
/* virtual & phys address size in low 2 bytes. */
|
||||
*eax = cpu->phys_bits;
|
||||
if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
|
||||
/* 64 bit processor */
|
||||
*eax = cpu->phys_bits; /* configurable physical bits */
|
||||
if (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57) {
|
||||
*eax |= 0x00003900; /* 57 bits virtual */
|
||||
} else {
|
||||
*eax |= 0x00003000; /* 48 bits virtual */
|
||||
}
|
||||
} else {
|
||||
*eax = cpu->phys_bits;
|
||||
*eax |= (cpu_x86_virtual_addr_width(env) << 8);
|
||||
}
|
||||
*ebx = env->features[FEAT_8000_0008_EBX];
|
||||
if (cs->nr_cores * cs->nr_threads > 1) {
|
||||
@ -5651,8 +5655,9 @@ static void x86_cpu_reset(DeviceState *dev)
|
||||
env->old_exception = -1;
|
||||
|
||||
/* init to reset state */
|
||||
|
||||
env->int_ctl = 0;
|
||||
env->hflags2 |= HF2_GIF_MASK;
|
||||
env->hflags2 |= HF2_VGIF_MASK;
|
||||
env->hflags &= ~HF_GUEST_MASK;
|
||||
|
||||
cpu_x86_update_cr0(env, 0x60000010);
|
||||
@ -6536,10 +6541,12 @@ int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request)
|
||||
!(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
|
||||
return CPU_INTERRUPT_HARD;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
} else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
||||
} else if (env->hflags2 & HF2_VGIF_MASK) {
|
||||
if((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
||||
(env->eflags & IF_MASK) &&
|
||||
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
||||
return CPU_INTERRUPT_VIRQ;
|
||||
return CPU_INTERRUPT_VIRQ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +203,7 @@ typedef enum X86Seg {
|
||||
#define HF2_MPX_PR_SHIFT 5 /* BNDCFGx.BNDPRESERVE */
|
||||
#define HF2_NPT_SHIFT 6 /* Nested Paging enabled */
|
||||
#define HF2_IGNNE_SHIFT 7 /* Ignore CR0.NE=0 */
|
||||
#define HF2_VGIF_SHIFT 8 /* Can take VIRQ*/
|
||||
|
||||
#define HF2_GIF_MASK (1 << HF2_GIF_SHIFT)
|
||||
#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
|
||||
@ -212,6 +213,7 @@ typedef enum X86Seg {
|
||||
#define HF2_MPX_PR_MASK (1 << HF2_MPX_PR_SHIFT)
|
||||
#define HF2_NPT_MASK (1 << HF2_NPT_SHIFT)
|
||||
#define HF2_IGNNE_MASK (1 << HF2_IGNNE_SHIFT)
|
||||
#define HF2_VGIF_MASK (1 << HF2_VGIF_SHIFT)
|
||||
|
||||
#define CR0_PE_SHIFT 0
|
||||
#define CR0_MP_SHIFT 1
|
||||
@ -257,6 +259,7 @@ typedef enum X86Seg {
|
||||
| CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \
|
||||
| CR4_MCE_MASK | CR4_PGE_MASK | CR4_PCE_MASK \
|
||||
| CR4_OSFXSR_MASK | CR4_OSXMMEXCPT_MASK |CR4_UMIP_MASK \
|
||||
| CR4_LA57_MASK \
|
||||
| CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \
|
||||
| CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK))
|
||||
|
||||
@ -1577,6 +1580,7 @@ typedef struct CPUX86State {
|
||||
uint64_t nested_cr3;
|
||||
uint32_t nested_pg_mode;
|
||||
uint8_t v_tpr;
|
||||
uint32_t int_ctl;
|
||||
|
||||
/* KVM states, automatically cleared on reset */
|
||||
uint8_t nmi_injected;
|
||||
@ -1954,6 +1958,8 @@ typedef struct PropValue {
|
||||
} PropValue;
|
||||
void x86_cpu_apply_props(X86CPU *cpu, PropValue *props);
|
||||
|
||||
uint32_t cpu_x86_virtual_addr_width(CPUX86State *env);
|
||||
|
||||
/* cpu.c other functions (cpuid) */
|
||||
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
uint32_t *eax, uint32_t *ebx,
|
||||
@ -2240,6 +2246,23 @@ static inline uint64_t cr4_reserved_bits(CPUX86State *env)
|
||||
return reserved_bits;
|
||||
}
|
||||
|
||||
static inline bool ctl_has_irq(CPUX86State *env)
|
||||
{
|
||||
uint32_t int_prio;
|
||||
uint32_t tpr;
|
||||
|
||||
int_prio = (env->int_ctl & V_INTR_PRIO_MASK) >> V_INTR_PRIO_SHIFT;
|
||||
tpr = env->int_ctl & V_TPR_MASK;
|
||||
|
||||
if (env->int_ctl & V_IGN_TPR_MASK) {
|
||||
return (env->int_ctl & V_IRQ_MASK);
|
||||
}
|
||||
|
||||
return (env->int_ctl & V_IRQ_MASK) && (int_prio >= tpr);
|
||||
}
|
||||
|
||||
hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
|
||||
int *prot);
|
||||
#if defined(TARGET_X86_64) && \
|
||||
defined(CONFIG_USER_ONLY) && \
|
||||
defined(CONFIG_LINUX)
|
||||
|
@ -203,7 +203,7 @@ static int cpu_pre_save(void *opaque)
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
env->v_tpr = env->int_ctl & V_TPR_MASK;
|
||||
/* FPU */
|
||||
env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
|
||||
env->fptag_vmstate = 0;
|
||||
@ -1356,6 +1356,25 @@ static const VMStateDescription vmstate_svm_npt = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool svm_guest_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
return tcg_enabled() && env->int_ctl;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_svm_guest = {
|
||||
.name = "cpu/svm_guest",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = svm_guest_needed,
|
||||
.fields = (VMStateField[]){
|
||||
VMSTATE_UINT32(env.int_ctl, X86CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef TARGET_X86_64
|
||||
static bool intel_efer32_needed(void *opaque)
|
||||
{
|
||||
@ -1524,6 +1543,7 @@ const VMStateDescription vmstate_x86_cpu = {
|
||||
&vmstate_msr_intel_pt,
|
||||
&vmstate_msr_virt_ssbd,
|
||||
&vmstate_svm_npt,
|
||||
&vmstate_svm_guest,
|
||||
#ifndef TARGET_X86_64
|
||||
&vmstate_efer32,
|
||||
#endif
|
||||
|
@ -1132,13 +1132,14 @@ static MemoryListener nvmm_memory_listener = {
|
||||
};
|
||||
|
||||
static void
|
||||
nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
|
||||
nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
|
||||
size_t max_size)
|
||||
{
|
||||
struct nvmm_machine *mach = get_nvmm_mach();
|
||||
uintptr_t hva = (uintptr_t)host;
|
||||
int ret;
|
||||
|
||||
ret = nvmm_hva_map(mach, hva, size);
|
||||
ret = nvmm_hva_map(mach, hva, max_size);
|
||||
|
||||
if (ret == -1) {
|
||||
error_report("NVMM: Failed to map HVA, HostVA:%p "
|
||||
|
@ -9,6 +9,12 @@
|
||||
#define V_IRQ_SHIFT 8
|
||||
#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
|
||||
|
||||
#define V_GIF_ENABLED_SHIFT 25
|
||||
#define V_GIF_ENABLED_MASK (1 << V_GIF_ENABLED_SHIFT)
|
||||
|
||||
#define V_GIF_SHIFT 9
|
||||
#define V_GIF_MASK (1 << V_GIF_SHIFT)
|
||||
|
||||
#define V_INTR_PRIO_SHIFT 16
|
||||
#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
|
||||
|
||||
@ -18,6 +24,8 @@
|
||||
#define V_INTR_MASKING_SHIFT 24
|
||||
#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
|
||||
|
||||
#define V_VMLOAD_VMSAVE_ENABLED_MASK (1 << 1)
|
||||
|
||||
#define SVM_INTERRUPT_SHADOW_MASK 1
|
||||
|
||||
#define SVM_IOIO_STR_SHIFT 2
|
||||
|
@ -1166,7 +1166,6 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
break;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
case CPU_INTERRUPT_VIRQ:
|
||||
/* FIXME: this should respect TPR */
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0);
|
||||
intno = x86_ldl_phys(cs, env->vm_vmcb
|
||||
+ offsetof(struct vmcb, control.int_vector));
|
||||
@ -1174,6 +1173,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
"Servicing virtual hardware INT=0x%02x\n", intno);
|
||||
do_interrupt_x86_hardirq(env, intno, 1);
|
||||
cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
|
||||
env->int_ctl &= ~V_IRQ_MASK;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ do_check_protect_pse36:
|
||||
return error_code;
|
||||
}
|
||||
|
||||
static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
|
||||
hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
|
||||
int *prot)
|
||||
{
|
||||
CPUX86State *env = &X86_CPU(cs)->env;
|
||||
|
@ -73,7 +73,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
|
||||
if (!(env->hflags2 & HF2_VINTR_MASK)) {
|
||||
val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
|
||||
} else {
|
||||
val = env->v_tpr;
|
||||
val = env->int_ctl & V_TPR_MASK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -121,7 +121,14 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
|
||||
cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
env->v_tpr = t0 & 0x0f;
|
||||
env->int_ctl = (env->int_ctl & ~V_TPR_MASK) | (t0 & V_TPR_MASK);
|
||||
|
||||
CPUState *cs = env_cpu(env);
|
||||
if (ctl_has_irq(env)) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_VIRQ);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_VIRQ);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
env->cr[reg] = t0;
|
||||
|
@ -41,6 +41,16 @@ static inline void svm_save_seg(CPUX86State *env, hwaddr addr,
|
||||
((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
|
||||
}
|
||||
|
||||
/*
|
||||
* VMRUN and VMLOAD canonicalizes (i.e., sign-extend to bit 63) all base
|
||||
* addresses in the segment registers that have been loaded.
|
||||
*/
|
||||
static inline void svm_canonicalization(CPUX86State *env, target_ulong *seg_base)
|
||||
{
|
||||
uint16_t shift_amt = 64 - cpu_x86_virtual_addr_width(env);
|
||||
*seg_base = ((((long) *seg_base) << shift_amt) >> shift_amt);
|
||||
}
|
||||
|
||||
static inline void svm_load_seg(CPUX86State *env, hwaddr addr,
|
||||
SegmentCache *sc)
|
||||
{
|
||||
@ -53,6 +63,7 @@ static inline void svm_load_seg(CPUX86State *env, hwaddr addr,
|
||||
sc->limit = x86_ldl_phys(cs, addr + offsetof(struct vmcb_seg, limit));
|
||||
flags = x86_lduw_phys(cs, addr + offsetof(struct vmcb_seg, attrib));
|
||||
sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
|
||||
svm_canonicalization(env, &sc->base);
|
||||
}
|
||||
|
||||
static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr,
|
||||
@ -65,16 +76,6 @@ static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr,
|
||||
sc->base, sc->limit, sc->flags);
|
||||
}
|
||||
|
||||
static inline bool ctl_has_irq(uint32_t int_ctl)
|
||||
{
|
||||
uint32_t int_prio;
|
||||
uint32_t tpr;
|
||||
|
||||
int_prio = (int_ctl & V_INTR_PRIO_MASK) >> V_INTR_PRIO_SHIFT;
|
||||
tpr = int_ctl & V_TPR_MASK;
|
||||
return (int_ctl & V_IRQ_MASK) && (int_prio >= tpr);
|
||||
}
|
||||
|
||||
static inline bool is_efer_invalid_state (CPUX86State *env)
|
||||
{
|
||||
if (!(env->efer & MSR_EFER_SVME)) {
|
||||
@ -110,6 +111,39 @@ static inline bool is_efer_invalid_state (CPUX86State *env)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool virtual_gif_enabled(CPUX86State *env)
|
||||
{
|
||||
if (likely(env->hflags & HF_GUEST_MASK)) {
|
||||
return (env->features[FEAT_SVM] & CPUID_SVM_VGIF)
|
||||
&& (env->int_ctl & V_GIF_ENABLED_MASK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool virtual_vm_load_save_enabled(CPUX86State *env, uint32_t exit_code, uintptr_t retaddr)
|
||||
{
|
||||
uint64_t lbr_ctl;
|
||||
|
||||
if (likely(env->hflags & HF_GUEST_MASK)) {
|
||||
if (likely(!(env->hflags2 & HF2_NPT_MASK)) || !(env->efer & MSR_EFER_LMA)) {
|
||||
cpu_vmexit(env, exit_code, 0, retaddr);
|
||||
}
|
||||
|
||||
lbr_ctl = x86_ldl_phys(env_cpu(env), env->vm_vmcb + offsetof(struct vmcb,
|
||||
control.lbr_ctl));
|
||||
return (env->features[FEAT_SVM] & CPUID_SVM_V_VMSAVE_VMLOAD)
|
||||
&& (lbr_ctl & V_VMLOAD_VMSAVE_ENABLED_MASK);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool virtual_gif_set(CPUX86State *env)
|
||||
{
|
||||
return !virtual_gif_enabled(env) || (env->int_ctl & V_GIF_MASK);
|
||||
}
|
||||
|
||||
void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
@ -117,7 +151,6 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
target_ulong addr;
|
||||
uint64_t nested_ctl;
|
||||
uint32_t event_inj;
|
||||
uint32_t int_ctl;
|
||||
uint32_t asid;
|
||||
uint64_t new_cr0;
|
||||
uint64_t new_cr3;
|
||||
@ -245,16 +278,6 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb +
|
||||
offsetof(struct vmcb, control.tsc_offset));
|
||||
|
||||
env->gdt.base = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||
save.gdtr.base));
|
||||
env->gdt.limit = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||
save.gdtr.limit));
|
||||
|
||||
env->idt.base = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||
save.idtr.base));
|
||||
env->idt.limit = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||
save.idtr.limit));
|
||||
|
||||
new_cr0 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr0));
|
||||
if (new_cr0 & SVM_CR0_RESERVED_MASK) {
|
||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||
@ -280,11 +303,10 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
cpu_x86_update_cr3(env, new_cr3);
|
||||
env->cr[2] = x86_ldq_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, save.cr2));
|
||||
int_ctl = x86_ldl_phys(cs,
|
||||
env->int_ctl = x86_ldl_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
|
||||
env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
|
||||
if (int_ctl & V_INTR_MASKING_MASK) {
|
||||
env->v_tpr = int_ctl & V_TPR_MASK;
|
||||
if (env->int_ctl & V_INTR_MASKING_MASK) {
|
||||
env->hflags2 |= HF2_VINTR_MASK;
|
||||
if (env->eflags & IF_MASK) {
|
||||
env->hflags2 |= HF2_HIF_MASK;
|
||||
@ -308,6 +330,10 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
R_SS);
|
||||
svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.ds),
|
||||
R_DS);
|
||||
svm_load_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.idtr),
|
||||
&env->idt);
|
||||
svm_load_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.gdtr),
|
||||
&env->gdt);
|
||||
|
||||
env->eip = x86_ldq_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, save.rip));
|
||||
@ -346,12 +372,16 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
|
||||
env->hflags2 |= HF2_GIF_MASK;
|
||||
|
||||
if (ctl_has_irq(int_ctl)) {
|
||||
if (ctl_has_irq(env)) {
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
|
||||
}
|
||||
|
||||
if (virtual_gif_set(env)) {
|
||||
env->hflags2 |= HF2_VGIF_MASK;
|
||||
}
|
||||
|
||||
/* maybe we need to inject an event */
|
||||
event_inj = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||
control.event_inj));
|
||||
@ -420,6 +450,7 @@ void helper_vmload(CPUX86State *env, int aflag)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong addr;
|
||||
int prot;
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
||||
|
||||
@ -429,6 +460,10 @@ void helper_vmload(CPUX86State *env, int aflag)
|
||||
addr = (uint32_t)env->regs[R_EAX];
|
||||
}
|
||||
|
||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
|
||||
addr = get_hphys(cs, addr, MMU_DATA_LOAD, &prot);
|
||||
}
|
||||
|
||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx
|
||||
"\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
|
||||
addr, x86_ldq_phys(cs, addr + offsetof(struct vmcb,
|
||||
@ -446,6 +481,7 @@ void helper_vmload(CPUX86State *env, int aflag)
|
||||
env->lstar = x86_ldq_phys(cs, addr + offsetof(struct vmcb, save.lstar));
|
||||
env->cstar = x86_ldq_phys(cs, addr + offsetof(struct vmcb, save.cstar));
|
||||
env->fmask = x86_ldq_phys(cs, addr + offsetof(struct vmcb, save.sfmask));
|
||||
svm_canonicalization(env, &env->kernelgsbase);
|
||||
#endif
|
||||
env->star = x86_ldq_phys(cs, addr + offsetof(struct vmcb, save.star));
|
||||
env->sysenter_cs = x86_ldq_phys(cs,
|
||||
@ -454,12 +490,14 @@ void helper_vmload(CPUX86State *env, int aflag)
|
||||
save.sysenter_esp));
|
||||
env->sysenter_eip = x86_ldq_phys(cs, addr + offsetof(struct vmcb,
|
||||
save.sysenter_eip));
|
||||
|
||||
}
|
||||
|
||||
void helper_vmsave(CPUX86State *env, int aflag)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong addr;
|
||||
int prot;
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
||||
|
||||
@ -469,6 +507,10 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
||||
addr = (uint32_t)env->regs[R_EAX];
|
||||
}
|
||||
|
||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
|
||||
addr = get_hphys(cs, addr, MMU_DATA_STORE, &prot);
|
||||
}
|
||||
|
||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx
|
||||
"\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
|
||||
addr, x86_ldq_phys(cs,
|
||||
@ -503,13 +545,25 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
||||
void helper_stgi(CPUX86State *env)
|
||||
{
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0, GETPC());
|
||||
env->hflags2 |= HF2_GIF_MASK;
|
||||
|
||||
if (virtual_gif_enabled(env)) {
|
||||
env->int_ctl |= V_GIF_MASK;
|
||||
env->hflags2 |= HF2_VGIF_MASK;
|
||||
} else {
|
||||
env->hflags2 |= HF2_GIF_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_clgi(CPUX86State *env)
|
||||
{
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0, GETPC());
|
||||
env->hflags2 &= ~HF2_GIF_MASK;
|
||||
|
||||
if (virtual_gif_enabled(env)) {
|
||||
env->int_ctl &= ~V_GIF_MASK;
|
||||
env->hflags2 &= ~HF2_VGIF_MASK;
|
||||
} else {
|
||||
env->hflags2 &= ~HF2_GIF_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
bool cpu_svm_has_intercept(CPUX86State *env, uint32_t type)
|
||||
@ -654,7 +708,6 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
|
||||
void do_vmexit(CPUX86State *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
uint32_t int_ctl;
|
||||
|
||||
if (env->hflags & HF_INHIBIT_IRQ_MASK) {
|
||||
x86_stl_phys(cs,
|
||||
@ -697,16 +750,8 @@ void do_vmexit(CPUX86State *env)
|
||||
env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
|
||||
x86_stq_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
|
||||
|
||||
int_ctl = x86_ldl_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
|
||||
int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
|
||||
int_ctl |= env->v_tpr & V_TPR_MASK;
|
||||
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
|
||||
int_ctl |= V_IRQ_MASK;
|
||||
}
|
||||
x86_stl_phys(cs,
|
||||
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
|
||||
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), env->int_ctl);
|
||||
|
||||
x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.rflags),
|
||||
cpu_compute_eflags(env));
|
||||
@ -729,6 +774,7 @@ void do_vmexit(CPUX86State *env)
|
||||
env->intercept = 0;
|
||||
env->intercept_exceptions = 0;
|
||||
cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
|
||||
env->int_ctl = 0;
|
||||
env->tsc_offset = 0;
|
||||
|
||||
env->gdt.base = x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
|
||||
@ -796,6 +842,7 @@ void do_vmexit(CPUX86State *env)
|
||||
env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
|
||||
|
||||
env->hflags2 &= ~HF2_GIF_MASK;
|
||||
env->hflags2 &= ~HF2_VGIF_MASK;
|
||||
/* FIXME: Resets the current ASID register to zero (host ASID). */
|
||||
|
||||
/* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
|
||||
|
@ -2,6 +2,7 @@
|
||||
specific_ss.add(files('control-target.c'))
|
||||
|
||||
trace_events_files = []
|
||||
dtrace = find_program('dtrace', required: 'CONFIG_TRACE_DTRACE' in config_host)
|
||||
foreach dir : [ '.' ] + trace_events_subdirs
|
||||
trace_events_file = meson.source_root() / dir / 'trace-events'
|
||||
trace_events_files += [ trace_events_file ]
|
||||
@ -39,13 +40,13 @@ foreach dir : [ '.' ] + trace_events_subdirs
|
||||
trace_dtrace_h = custom_target(fmt.format('trace-dtrace', 'h'),
|
||||
output: fmt.format('trace-dtrace', 'h'),
|
||||
input: trace_dtrace,
|
||||
command: [ 'dtrace', '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-h', '-s', '@INPUT@' ])
|
||||
command: [ dtrace, '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-h', '-s', '@INPUT@' ])
|
||||
trace_ss.add(trace_dtrace_h)
|
||||
if host_machine.system() != 'darwin'
|
||||
trace_dtrace_o = custom_target(fmt.format('trace-dtrace', 'o'),
|
||||
output: fmt.format('trace-dtrace', 'o'),
|
||||
input: trace_dtrace,
|
||||
command: [ 'dtrace', '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-G', '-s', '@INPUT@' ])
|
||||
command: [ dtrace, '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-G', '-s', '@INPUT@' ])
|
||||
trace_ss.add(trace_dtrace_o)
|
||||
endif
|
||||
|
||||
|
@ -105,8 +105,6 @@ if config_host.has_key('CONFIG_SPICE') and config_host.has_key('CONFIG_GIO')
|
||||
ui_modules += {'spice-app': spice_ss}
|
||||
endif
|
||||
|
||||
keymap_gen = find_program('keycodemapdb/tools/keymap-gen')
|
||||
|
||||
keymaps = [
|
||||
['atset1', 'qcode'],
|
||||
['linux', 'qcode'],
|
||||
@ -134,7 +132,7 @@ if have_system or xkbcommon.found()
|
||||
output: output,
|
||||
capture: true,
|
||||
input: files('keycodemapdb/data/keymaps.csv'),
|
||||
command: [python.full_path(), files('keycodemapdb/tools/keymap-gen'),
|
||||
command: [python, files('keycodemapdb/tools/keymap-gen'),
|
||||
'code-map',
|
||||
'--lang', 'glib2',
|
||||
'--varname', 'qemu_input_map_@0@_to_@1@'.format(e[0], e[1]),
|
||||
|
@ -537,9 +537,28 @@ static void *qemu_thread_start(void *args)
|
||||
QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
|
||||
g_free(qemu_thread_args->name);
|
||||
g_free(qemu_thread_args);
|
||||
|
||||
/*
|
||||
* GCC 11 with glibc 2.17 on PowerPC reports
|
||||
*
|
||||
* qemu-thread-posix.c:540:5: error: ‘__sigsetjmp’ accessing 656 bytes
|
||||
* in a region of size 528 [-Werror=stringop-overflow=]
|
||||
* 540 | pthread_cleanup_push(qemu_thread_atexit_notify, NULL);
|
||||
* | ^~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* which is clearly nonsense.
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
|
||||
pthread_cleanup_push(qemu_thread_atexit_notify, NULL);
|
||||
r = start_routine(arg);
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user