aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/about/index.rst3
-rw-r--r--docs/devel/code-of-conduct.rst4
-rw-r--r--docs/devel/index.rst3
-rw-r--r--docs/index.rst1
-rw-r--r--docs/interop/index.rst3
-rw-r--r--docs/specs/index.rst3
-rw-r--r--docs/system/cpu-models-x86.rst.inc4
-rw-r--r--docs/system/i386/cpu.rst1
-rw-r--r--docs/system/index.rst3
-rw-r--r--docs/system/qemu-block-drivers.rst4
-rw-r--r--docs/system/qemu-cpu-models.rst10
-rw-r--r--docs/system/qemu-manpage.rst10
-rw-r--r--docs/system/target-i386.rst8
-rw-r--r--docs/tools/index.rst3
-rw-r--r--docs/tools/qemu-img.rst1
-rw-r--r--docs/tools/qemu-nbd.rst1
-rw-r--r--docs/tools/qemu-pr-helper.rst1
-rw-r--r--docs/tools/qemu-storage-daemon.rst1
-rw-r--r--docs/tools/qemu-trace-stap.rst1
-rw-r--r--docs/user/index.rst3
-rw-r--r--hw/nvram/fw_cfg.c1
-rw-r--r--include/sysemu/nvmm.h7
-rw-r--r--meson.build2
-rw-r--r--pc-bios/keymaps/meson.build3
-rw-r--r--target/i386/cpu.c31
-rw-r--r--target/i386/cpu.h23
-rw-r--r--target/i386/machine.c22
-rw-r--r--target/i386/nvmm/nvmm-all.c5
-rw-r--r--target/i386/svm.h8
-rw-r--r--target/i386/tcg/seg_helper.c2
-rw-r--r--target/i386/tcg/sysemu/excp_helper.c2
-rw-r--r--target/i386/tcg/sysemu/misc_helper.c11
-rw-r--r--target/i386/tcg/sysemu/svm_helper.c121
-rw-r--r--trace/meson.build5
-rw-r--r--ui/meson.build4
-rw-r--r--util/qemu-thread-posix.c19
36 files changed, 251 insertions, 83 deletions
diff --git a/docs/about/index.rst b/docs/about/index.rst
index beb762aa0a..5bea653c07 100644
--- a/docs/about/index.rst
+++ b/docs/about/index.rst
@@ -1,5 +1,6 @@
+----------
About QEMU
-==========
+----------
QEMU is a generic and open source machine emulator and virtualizer.
diff --git a/docs/devel/code-of-conduct.rst b/docs/devel/code-of-conduct.rst
index 277b5250d1..195444d1b4 100644
--- a/docs/devel/code-of-conduct.rst
+++ b/docs/devel/code-of-conduct.rst
@@ -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/>`__.
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 5522db7241..f95df10b3e 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -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
diff --git a/docs/index.rst b/docs/index.rst
index 5f7eaaa632..0b9ee9901d 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -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!
================================
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
index f9801a9c20..47b9ed82bb 100644
--- a/docs/interop/index.rst
+++ b/docs/interop/index.rst
@@ -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.
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index 65e9663916..ecc43896bb 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -1,5 +1,6 @@
+----------------------------------------------
System Emulation Guest Hardware Specifications
-==============================================
+----------------------------------------------
This section of the manual contains specifications of
guest hardware that is specific to QEMU.
diff --git a/docs/system/cpu-models-x86.rst.inc b/docs/system/cpu-models-x86.rst.inc
index 9119f5dff5..6e8be7d79b 100644
--- a/docs/system/cpu-models-x86.rst.inc
+++ b/docs/system/cpu-models-x86.rst.inc
@@ -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.
diff --git a/docs/system/i386/cpu.rst b/docs/system/i386/cpu.rst
new file mode 100644
index 0000000000..738719da9a
--- /dev/null
+++ b/docs/system/i386/cpu.rst
@@ -0,0 +1 @@
+.. include:: ../cpu-models-x86.rst.inc
diff --git a/docs/system/index.rst b/docs/system/index.rst
index 7b9276c05f..73bbedbc22 100644
--- a/docs/system/index.rst
+++ b/docs/system/index.rst
@@ -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).
diff --git a/docs/system/qemu-block-drivers.rst b/docs/system/qemu-block-drivers.rst
index bd99d4fa8e..c2c0114cec 100644
--- a/docs/system/qemu-block-drivers.rst
+++ b/docs/system/qemu-block-drivers.rst
@@ -1,18 +1,22 @@
:orphan:
+============================
QEMU block drivers reference
============================
+--------
Synopsis
--------
QEMU block driver reference manual
+-----------
Description
-----------
.. include:: qemu-block-drivers.rst.inc
+--------
See also
--------
diff --git a/docs/system/qemu-cpu-models.rst b/docs/system/qemu-cpu-models.rst
index 53d7538c47..5cf6e46f8a 100644
--- a/docs/system/qemu-cpu-models.rst
+++ b/docs/system/qemu-cpu-models.rst
@@ -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.
diff --git a/docs/system/qemu-manpage.rst b/docs/system/qemu-manpage.rst
index e9a25d0680..c47a412758 100644
--- a/docs/system/qemu-manpage.rst
+++ b/docs/system/qemu-manpage.rst
@@ -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
--------
diff --git a/docs/system/target-i386.rst b/docs/system/target-i386.rst
index 22ba5ce2c0..c9720a8cd1 100644
--- a/docs/system/target-i386.rst
+++ b/docs/system/target-i386.rst
@@ -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:
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
index ef6041a490..1edd5a8054 100644
--- a/docs/tools/index.rst
+++ b/docs/tools/index.rst
@@ -1,5 +1,6 @@
+-----
Tools
-=====
+-----
This section of the manual documents QEMU's "tools": its
command line utilities and other standalone programs.
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index b7d602a288..fe6c30d509 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -1,3 +1,4 @@
+=======================
QEMU disk image utility
=======================
diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst
index ee862fa0bc..e39a9f4b1a 100644
--- a/docs/tools/qemu-nbd.rst
+++ b/docs/tools/qemu-nbd.rst
@@ -1,3 +1,4 @@
+=====================================
QEMU Disk Network Block Device Server
=====================================
diff --git a/docs/tools/qemu-pr-helper.rst b/docs/tools/qemu-pr-helper.rst
index ac036180ac..eaebe40da0 100644
--- a/docs/tools/qemu-pr-helper.rst
+++ b/docs/tools/qemu-pr-helper.rst
@@ -1,3 +1,4 @@
+==================================
QEMU persistent reservation helper
==================================
diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst
index 3ec4bdd914..b8ef4486f1 100644
--- a/docs/tools/qemu-storage-daemon.rst
+++ b/docs/tools/qemu-storage-daemon.rst
@@ -1,3 +1,4 @@
+===================
QEMU Storage Daemon
===================
diff --git a/docs/tools/qemu-trace-stap.rst b/docs/tools/qemu-trace-stap.rst
index fb70445c75..d53073b52b 100644
--- a/docs/tools/qemu-trace-stap.rst
+++ b/docs/tools/qemu-trace-stap.rst
@@ -1,3 +1,4 @@
+=========================
QEMU SystemTap trace tool
=========================
diff --git a/docs/user/index.rst b/docs/user/index.rst
index 9faa4badd7..2c4e29f3db 100644
--- a/docs/user/index.rst
+++ b/docs/user/index.rst
@@ -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
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 9b8dcca4ea..c06b30de11 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -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
};
diff --git a/include/sysemu/nvmm.h b/include/sysemu/nvmm.h
index 6d216599b0..833670fccb 100644
--- a/include/sysemu/nvmm.h
+++ b/include/sysemu/nvmm.h
@@ -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 */
diff --git a/meson.build b/meson.build
index 9a64d16943..7d7d14a4bc 100644
--- a/meson.build
+++ b/meson.build
@@ -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)
diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build
index 05eda6c0d2..44247a12b5 100644
--- a/pc-bios/keymaps/meson.build
+++ b/pc-bios/keymaps/meson.build
@@ -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
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 97e250e876..6b029f1bdf 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -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
}
}
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 6c50d3ab4f..71ae3141c3 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -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)
diff --git a/target/i386/machine.c b/target/i386/machine.c
index f6f094f1c9..b0943118d1 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -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
diff --git a/target/i386/nvmm/nvmm-all.c b/target/i386/nvmm/nvmm-all.c
index 28dee4c5ee..a488b00e90 100644
--- a/target/i386/nvmm/nvmm-all.c
+++ b/target/i386/nvmm/nvmm-all.c
@@ -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 "
diff --git a/target/i386/svm.h b/target/i386/svm.h
index adc058dc76..f9a785489d 100644
--- a/target/i386/svm.h
+++ b/target/i386/svm.h
@@ -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
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 3ed20ca31d..cef68b610a 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -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
}
diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
index b6d940e04e..7af887be4d 100644
--- a/target/i386/tcg/sysemu/excp_helper.c
+++ b/target/i386/tcg/sysemu/excp_helper.c
@@ -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;
diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
index e7a2ebde81..9ccaa054c4 100644
--- a/target/i386/tcg/sysemu/misc_helper.c
+++ b/target/i386/tcg/sysemu/misc_helper.c
@@ -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;
diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c
index 0d549b3d6c..6d39611eb6 100644
--- a/target/i386/tcg/sysemu/svm_helper.c
+++ b/target/i386/tcg/sysemu/svm_helper.c
@@ -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. */
diff --git a/trace/meson.build b/trace/meson.build
index ef18f11d64..e401e7c415 100644
--- a/trace/meson.build
+++ b/trace/meson.build
@@ -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
diff --git a/ui/meson.build b/ui/meson.build
index 7d25c1b95b..a73beb0e54 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -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]),
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index fd9d714038..6c5004220d 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -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;
}