* 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:
Peter Maydell 2021-09-13 13:33:21 +01:00
commit 7d79344d4f
36 changed files with 251 additions and 83 deletions

View File

@ -1,5 +1,6 @@
----------
About QEMU
==========
----------
QEMU is a generic and open source machine emulator and virtualizer.

View File

@ -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/>`__.

View File

@ -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

View File

@ -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!
================================

View File

@ -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.

View File

@ -1,5 +1,6 @@
----------------------------------------------
System Emulation Guest Hardware Specifications
==============================================
----------------------------------------------
This section of the manual contains specifications of
guest hardware that is specific to QEMU.

View File

@ -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
View File

@ -0,0 +1 @@
.. include:: ../cpu-models-x86.rst.inc

View File

@ -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).

View File

@ -1,18 +1,22 @@
:orphan:
============================
QEMU block drivers reference
============================
--------
Synopsis
--------
QEMU block driver reference manual
-----------
Description
-----------
.. include:: qemu-block-drivers.rst.inc
--------
See also
--------

View File

@ -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.

View File

@ -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
--------

View File

@ -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:

View File

@ -1,5 +1,6 @@
-----
Tools
=====
-----
This section of the manual documents QEMU's "tools": its
command line utilities and other standalone programs.

View File

@ -1,3 +1,4 @@
=======================
QEMU disk image utility
=======================

View File

@ -1,3 +1,4 @@
=====================================
QEMU Disk Network Block Device Server
=====================================

View File

@ -1,3 +1,4 @@
==================================
QEMU persistent reservation helper
==================================

View File

@ -1,3 +1,4 @@
===================
QEMU Storage Daemon
===================

View File

@ -1,3 +1,4 @@
=========================
QEMU SystemTap trace tool
=========================

View File

@ -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

View File

@ -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
};

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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)

View File

@ -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

View File

@ -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 "

View File

@ -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

View File

@ -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
}

View File

@ -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;

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -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]),

View File

@ -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;
}