* scsi-disk: Don't silently truncate serial number
* backends/hostmem: Report error on unavailable qemu_madvise() features or unaligned memory sizes * target/i386: fixes and documentation for INHIBIT_IRQ/TF/RF and debugging * i386/hvf: Adds support for INVTSC cpuid bit * i386/hvf: Fixes for dirty memory tracking * i386/hvf: Use hv_vcpu_interrupt() and hv_vcpu_run_until() * hvf: Cleanups * stubs: fixes for --disable-system build * i386/kvm: support for FRED * i386/kvm: fix MCE handling on AMD hosts -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmZkF2oUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPNlQf+N9y6Eh0nMEEQ69twtV8ytglTY+uX FsogvnsXHNMVubOWmmeItM6kFXTAkR9cmFaL8dqI1Gs03xEQdQXbF1KejJZOAZVl RQMOW8Fg2Afr+0lwqCXHvhsmZ4hr5yUkRndyucA/E9AO2uGrtgwsWGDBGaHJOZIA lAsEMOZgKjXHZnefXjhMrvpk/QNovjEV6f1RHX3oKZjKSI5/G4IqGSmwNYToot8p 2fgs4Qti4+1gNyM2oBLq7cCMjMS61tSxOMH4uqVoIisjyckPlAFRvc+DXtKsUAAs 9AgM++pNgpB0IXv67czRUNdRoK7OI8I0ULhI4qHXi6Yg2QYAHqpQ6WL4Lg== =RP7U -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * scsi-disk: Don't silently truncate serial number * backends/hostmem: Report error on unavailable qemu_madvise() features or unaligned memory sizes * target/i386: fixes and documentation for INHIBIT_IRQ/TF/RF and debugging * i386/hvf: Adds support for INVTSC cpuid bit * i386/hvf: Fixes for dirty memory tracking * i386/hvf: Use hv_vcpu_interrupt() and hv_vcpu_run_until() * hvf: Cleanups * stubs: fixes for --disable-system build * i386/kvm: support for FRED * i386/kvm: fix MCE handling on AMD hosts # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmZkF2oUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroPNlQf+N9y6Eh0nMEEQ69twtV8ytglTY+uX # FsogvnsXHNMVubOWmmeItM6kFXTAkR9cmFaL8dqI1Gs03xEQdQXbF1KejJZOAZVl # RQMOW8Fg2Afr+0lwqCXHvhsmZ4hr5yUkRndyucA/E9AO2uGrtgwsWGDBGaHJOZIA # lAsEMOZgKjXHZnefXjhMrvpk/QNovjEV6f1RHX3oKZjKSI5/G4IqGSmwNYToot8p # 2fgs4Qti4+1gNyM2oBLq7cCMjMS61tSxOMH4uqVoIisjyckPlAFRvc+DXtKsUAAs # 9AgM++pNgpB0IXv67czRUNdRoK7OI8I0ULhI4qHXi6Yg2QYAHqpQ6WL4Lg== # =RP7U # -----END PGP SIGNATURE----- # gpg: Signature made Sat 08 Jun 2024 01:33:46 AM PDT # 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] * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (42 commits) python: mkvenv: remove ensure command Revert "python: use vendored tomli" i386: Add support for overflow recovery i386: Add support for SUCCOR feature i386: Fix MCE support for AMD hosts docs: i386: pc: Avoid mentioning limit of maximum vCPUs target/i386: Add get/set/migrate support for FRED MSRs target/i386: enumerate VMX nested-exception support vmxcap: add support for VMX FRED controls target/i386: mark CR4.FRED not reserved target/i386: add support for FRED in CPUID enumeration hvf: Makes assert_hvf_ok report failed expression i386/hvf: Updates API usage to use modern vCPU run function i386/hvf: In kick_vcpu use hv_vcpu_interrupt to force exit i386/hvf: Fixes dirty memory tracking by page granularity RX->RWX change hvf: Consistent types for vCPU handles i386/hvf: Fixes some compilation warnings i386/hvf: Adds support for INVTSC cpuid bit stubs/meson: Fix qemuutil build when --disable-system scsi-disk: Don't silently truncate serial number ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
3e246da2c3
@ -400,7 +400,7 @@ static int hvf_init_vcpu(CPUState *cpu)
|
|||||||
r = hv_vcpu_create(&cpu->accel->fd,
|
r = hv_vcpu_create(&cpu->accel->fd,
|
||||||
(hv_vcpu_exit_t **)&cpu->accel->exit, NULL);
|
(hv_vcpu_exit_t **)&cpu->accel->exit, NULL);
|
||||||
#else
|
#else
|
||||||
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->accel->fd, HV_VCPU_DEFAULT);
|
r = hv_vcpu_create(&cpu->accel->fd, HV_VCPU_DEFAULT);
|
||||||
#endif
|
#endif
|
||||||
cpu->accel->dirty = true;
|
cpu->accel->dirty = true;
|
||||||
assert_hvf_ok(r);
|
assert_hvf_ok(r);
|
||||||
|
@ -13,40 +13,33 @@
|
|||||||
#include "sysemu/hvf.h"
|
#include "sysemu/hvf.h"
|
||||||
#include "sysemu/hvf_int.h"
|
#include "sysemu/hvf_int.h"
|
||||||
|
|
||||||
void assert_hvf_ok(hv_return_t ret)
|
const char *hvf_return_string(hv_return_t ret)
|
||||||
|
{
|
||||||
|
switch (ret) {
|
||||||
|
case HV_SUCCESS: return "HV_SUCCESS";
|
||||||
|
case HV_ERROR: return "HV_ERROR";
|
||||||
|
case HV_BUSY: return "HV_BUSY";
|
||||||
|
case HV_BAD_ARGUMENT: return "HV_BAD_ARGUMENT";
|
||||||
|
case HV_NO_RESOURCES: return "HV_NO_RESOURCES";
|
||||||
|
case HV_NO_DEVICE: return "HV_NO_DEVICE";
|
||||||
|
case HV_UNSUPPORTED: return "HV_UNSUPPORTED";
|
||||||
|
#if defined(MAC_OS_VERSION_11_0) && \
|
||||||
|
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
||||||
|
case HV_DENIED: return "HV_DENIED";
|
||||||
|
#endif
|
||||||
|
default: return "[unknown hv_return value]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
|
||||||
|
const char *exp)
|
||||||
{
|
{
|
||||||
if (ret == HV_SUCCESS) {
|
if (ret == HV_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ret) {
|
error_report("Error: %s = %s (0x%x, at %s:%u)",
|
||||||
case HV_ERROR:
|
exp, hvf_return_string(ret), ret, file, line);
|
||||||
error_report("Error: HV_ERROR");
|
|
||||||
break;
|
|
||||||
case HV_BUSY:
|
|
||||||
error_report("Error: HV_BUSY");
|
|
||||||
break;
|
|
||||||
case HV_BAD_ARGUMENT:
|
|
||||||
error_report("Error: HV_BAD_ARGUMENT");
|
|
||||||
break;
|
|
||||||
case HV_NO_RESOURCES:
|
|
||||||
error_report("Error: HV_NO_RESOURCES");
|
|
||||||
break;
|
|
||||||
case HV_NO_DEVICE:
|
|
||||||
error_report("Error: HV_NO_DEVICE");
|
|
||||||
break;
|
|
||||||
case HV_UNSUPPORTED:
|
|
||||||
error_report("Error: HV_UNSUPPORTED");
|
|
||||||
break;
|
|
||||||
#if defined(MAC_OS_VERSION_11_0) && \
|
|
||||||
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
|
||||||
case HV_DENIED:
|
|
||||||
error_report("Error: HV_DENIED");
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
error_report("Unknown Error");
|
|
||||||
}
|
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ sgx_epc_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->aligned = true;
|
||||||
name = object_get_canonical_path(OBJECT(backend));
|
name = object_get_canonical_path(OBJECT(backend));
|
||||||
ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED;
|
ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED;
|
||||||
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||||
|
@ -80,6 +80,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
|||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->aligned = true;
|
||||||
name = host_memory_backend_get_name(backend);
|
name = host_memory_backend_get_name(backend);
|
||||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
|
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
|
||||||
|
@ -52,6 +52,7 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->aligned = true;
|
||||||
name = host_memory_backend_get_name(backend);
|
name = host_memory_backend_get_name(backend);
|
||||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "qemu/mmap-alloc.h"
|
#include "qemu/mmap-alloc.h"
|
||||||
#include "qemu/madvise.h"
|
#include "qemu/madvise.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
#include "hw/qdev-core.h"
|
#include "hw/qdev-core.h"
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
@ -169,19 +170,24 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
|
|||||||
{
|
{
|
||||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||||
|
|
||||||
if (!host_memory_backend_mr_inited(backend)) {
|
if (QEMU_MADV_MERGEABLE == QEMU_MADV_INVALID) {
|
||||||
backend->merge = value;
|
if (value) {
|
||||||
|
error_setg(errp, "Memory merging is not supported on this host");
|
||||||
|
}
|
||||||
|
assert(!backend->merge);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value != backend->merge) {
|
if (!host_memory_backend_mr_inited(backend) &&
|
||||||
|
value != backend->merge) {
|
||||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||||
uint64_t sz = memory_region_size(&backend->mr);
|
uint64_t sz = memory_region_size(&backend->mr);
|
||||||
|
|
||||||
qemu_madvise(ptr, sz,
|
qemu_madvise(ptr, sz,
|
||||||
value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
|
value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
|
||||||
backend->merge = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->merge = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool host_memory_backend_get_dump(Object *obj, Error **errp)
|
static bool host_memory_backend_get_dump(Object *obj, Error **errp)
|
||||||
@ -195,19 +201,24 @@ static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
|
|||||||
{
|
{
|
||||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||||
|
|
||||||
if (!host_memory_backend_mr_inited(backend)) {
|
if (QEMU_MADV_DONTDUMP == QEMU_MADV_INVALID) {
|
||||||
backend->dump = value;
|
if (!value) {
|
||||||
|
error_setg(errp, "Dumping guest memory cannot be disabled on this host");
|
||||||
|
}
|
||||||
|
assert(backend->dump);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value != backend->dump) {
|
if (host_memory_backend_mr_inited(backend) &&
|
||||||
|
value != backend->dump) {
|
||||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||||
uint64_t sz = memory_region_size(&backend->mr);
|
uint64_t sz = memory_region_size(&backend->mr);
|
||||||
|
|
||||||
qemu_madvise(ptr, sz,
|
qemu_madvise(ptr, sz,
|
||||||
value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
|
value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
|
||||||
backend->dump = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->dump = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
|
static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
|
||||||
@ -325,6 +336,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
|||||||
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
|
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
|
||||||
void *ptr;
|
void *ptr;
|
||||||
uint64_t sz;
|
uint64_t sz;
|
||||||
|
size_t pagesize;
|
||||||
bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
|
bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
|
||||||
|
|
||||||
if (!bc->alloc) {
|
if (!bc->alloc) {
|
||||||
@ -336,6 +348,14 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
|||||||
|
|
||||||
ptr = memory_region_get_ram_ptr(&backend->mr);
|
ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||||
sz = memory_region_size(&backend->mr);
|
sz = memory_region_size(&backend->mr);
|
||||||
|
pagesize = qemu_ram_pagesize(backend->mr.ram_block);
|
||||||
|
|
||||||
|
if (backend->aligned && !QEMU_IS_ALIGNED(sz, pagesize)) {
|
||||||
|
g_autofree char *pagesize_str = size_to_str(pagesize);
|
||||||
|
error_setg(errp, "backend '%s' memory size must be multiple of %s",
|
||||||
|
object_get_typename(OBJECT(uc)), pagesize_str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (backend->merge) {
|
if (backend->merge) {
|
||||||
qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
|
qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
|
||||||
|
4
configure
vendored
4
configure
vendored
@ -955,10 +955,6 @@ mkvenv="$python ${source_path}/python/scripts/mkvenv.py"
|
|||||||
|
|
||||||
# Finish preparing the virtual environment using vendored .whl files
|
# Finish preparing the virtual environment using vendored .whl files
|
||||||
|
|
||||||
if $python -c 'import sys; sys.exit(sys.version_info >= (3,11))'; then
|
|
||||||
$mkvenv ensure --dir "${source_path}/python/wheels" \
|
|
||||||
'tomli>=1.2.0' || exit 1
|
|
||||||
fi
|
|
||||||
$mkvenv ensuregroup --dir "${source_path}/python/wheels" \
|
$mkvenv ensuregroup --dir "${source_path}/python/wheels" \
|
||||||
${source_path}/pythondeps.toml meson || exit 1
|
${source_path}/pythondeps.toml meson || exit 1
|
||||||
|
|
||||||
|
@ -185,14 +185,13 @@ Bundled Python packages
|
|||||||
|
|
||||||
Python packages that are **mandatory** dependencies to build QEMU,
|
Python packages that are **mandatory** dependencies to build QEMU,
|
||||||
but are not available in all supported distros, are bundled with the
|
but are not available in all supported distros, are bundled with the
|
||||||
QEMU sources. Currently this includes Meson (outdated in CentOS 8
|
QEMU sources. The only one is currently Meson (outdated in Ubuntu
|
||||||
and derivatives, Ubuntu 20.04 and 22.04, and openSUSE Leap) and tomli
|
22.04 and openSUSE Leap).
|
||||||
(absent in Ubuntu 20.04).
|
|
||||||
|
|
||||||
If you need to update these, please do so by modifying and rerunning
|
In order to include a new or updated wheel, modify and rerun the
|
||||||
``python/scripts/vendor.py``. This script embeds the sha256 hash of
|
``python/scripts/vendor.py`` script. The script embeds the
|
||||||
package sources and checks it. The pypi.org web site provides an easy
|
sha256 hash of package sources and checks it. The pypi.org web site
|
||||||
way to retrieve the sha256 hash of the sources.
|
provides an easy way to retrieve the sha256 hash of the sources.
|
||||||
|
|
||||||
|
|
||||||
Stage 2: Meson
|
Stage 2: Meson
|
||||||
|
@ -36,7 +36,8 @@ The QEMU PC System emulator simulates the following peripherals:
|
|||||||
- PCI UHCI, OHCI, EHCI or XHCI USB controller and a virtual USB-1.1
|
- PCI UHCI, OHCI, EHCI or XHCI USB controller and a virtual USB-1.1
|
||||||
hub.
|
hub.
|
||||||
|
|
||||||
SMP is supported with up to 255 CPUs (and 4096 CPUs for PC Q35 machine).
|
SMP is supported with a large number of virtual CPUs (upper limit is
|
||||||
|
configuration dependent).
|
||||||
|
|
||||||
QEMU uses the PC BIOS from the Seabios project and the Plex86/Bochs LGPL
|
QEMU uses the PC BIOS from the Seabios project and the Plex86/Bochs LGPL
|
||||||
VGA BIOS.
|
VGA BIOS.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-visit-machine.h"
|
#include "qapi/qapi-visit-machine.h"
|
||||||
|
#include "qemu/madvise.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
@ -427,6 +428,10 @@ static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
|
|||||||
{
|
{
|
||||||
MachineState *ms = MACHINE(obj);
|
MachineState *ms = MACHINE(obj);
|
||||||
|
|
||||||
|
if (!value && QEMU_MADV_DONTDUMP == QEMU_MADV_INVALID) {
|
||||||
|
error_setg(errp, "Dumping guest memory cannot be disabled on this host");
|
||||||
|
return;
|
||||||
|
}
|
||||||
ms->dump_guest_core = value;
|
ms->dump_guest_core = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,6 +446,10 @@ static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
|
|||||||
{
|
{
|
||||||
MachineState *ms = MACHINE(obj);
|
MachineState *ms = MACHINE(obj);
|
||||||
|
|
||||||
|
if (value && QEMU_MADV_MERGEABLE == QEMU_MADV_INVALID) {
|
||||||
|
error_setg(errp, "Memory merging is not supported on this host");
|
||||||
|
return;
|
||||||
|
}
|
||||||
ms->mem_merge = value;
|
ms->mem_merge = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1129,7 +1138,7 @@ static void machine_initfn(Object *obj)
|
|||||||
container_get(obj, "/peripheral-anon");
|
container_get(obj, "/peripheral-anon");
|
||||||
|
|
||||||
ms->dump_guest_core = true;
|
ms->dump_guest_core = true;
|
||||||
ms->mem_merge = true;
|
ms->mem_merge = (QEMU_MADV_MERGEABLE != QEMU_MADV_INVALID);
|
||||||
ms->enable_graphics = true;
|
ms->enable_graphics = true;
|
||||||
ms->kernel_cmdline = g_strdup("");
|
ms->kernel_cmdline = g_strdup("");
|
||||||
ms->ram_size = mc->default_ram_size;
|
ms->ram_size = mc->default_ram_size;
|
||||||
|
@ -58,6 +58,9 @@
|
|||||||
|
|
||||||
#define TYPE_SCSI_DISK_BASE "scsi-disk-base"
|
#define TYPE_SCSI_DISK_BASE "scsi-disk-base"
|
||||||
|
|
||||||
|
#define MAX_SERIAL_LEN 36
|
||||||
|
#define MAX_SERIAL_LEN_FOR_DEVID 20
|
||||||
|
|
||||||
OBJECT_DECLARE_TYPE(SCSIDiskState, SCSIDiskClass, SCSI_DISK_BASE)
|
OBJECT_DECLARE_TYPE(SCSIDiskState, SCSIDiskClass, SCSI_DISK_BASE)
|
||||||
|
|
||||||
struct SCSIDiskClass {
|
struct SCSIDiskClass {
|
||||||
@ -648,8 +651,8 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
l = strlen(s->serial);
|
l = strlen(s->serial);
|
||||||
if (l > 36) {
|
if (l > MAX_SERIAL_LEN) {
|
||||||
l = 36;
|
l = MAX_SERIAL_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_scsi_disk_emulate_vpd_page_80(req->cmd.xfer);
|
trace_scsi_disk_emulate_vpd_page_80(req->cmd.xfer);
|
||||||
@ -2501,9 +2504,20 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
|||||||
if (!s->vendor) {
|
if (!s->vendor) {
|
||||||
s->vendor = g_strdup("QEMU");
|
s->vendor = g_strdup("QEMU");
|
||||||
}
|
}
|
||||||
|
if (s->serial && strlen(s->serial) > MAX_SERIAL_LEN) {
|
||||||
|
error_setg(errp, "The serial number can't be longer than %d characters",
|
||||||
|
MAX_SERIAL_LEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!s->device_id) {
|
if (!s->device_id) {
|
||||||
if (s->serial) {
|
if (s->serial) {
|
||||||
s->device_id = g_strdup_printf("%.20s", s->serial);
|
if (strlen(s->serial) > MAX_SERIAL_LEN_FOR_DEVID) {
|
||||||
|
error_setg(errp, "The serial number can't be longer than %d "
|
||||||
|
"characters when it is also used as the default for "
|
||||||
|
"device_id", MAX_SERIAL_LEN_FOR_DEVID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->device_id = g_strdup(s->serial);
|
||||||
} else {
|
} else {
|
||||||
const char *str = blk_name(s->qdev.conf.blk);
|
const char *str = blk_name(s->qdev.conf.blk);
|
||||||
if (str && *str) {
|
if (str && *str) {
|
||||||
|
@ -74,7 +74,7 @@ struct HostMemoryBackend {
|
|||||||
uint64_t size;
|
uint64_t size;
|
||||||
bool merge, dump, use_canonical_path;
|
bool merge, dump, use_canonical_path;
|
||||||
bool prealloc, is_mapped, share, reserve;
|
bool prealloc, is_mapped, share, reserve;
|
||||||
bool guest_memfd;
|
bool guest_memfd, aligned;
|
||||||
uint32_t prealloc_threads;
|
uint32_t prealloc_threads;
|
||||||
ThreadContext *prealloc_context;
|
ThreadContext *prealloc_context;
|
||||||
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
|
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
#include <Hypervisor/Hypervisor.h>
|
#include <Hypervisor/Hypervisor.h>
|
||||||
|
typedef hv_vcpu_t hvf_vcpuid;
|
||||||
#else
|
#else
|
||||||
#include <Hypervisor/hv.h>
|
#include <Hypervisor/hv.h>
|
||||||
|
typedef hv_vcpuid_t hvf_vcpuid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* hvf_slot flags */
|
/* hvf_slot flags */
|
||||||
@ -50,7 +52,7 @@ struct HVFState {
|
|||||||
extern HVFState *hvf_state;
|
extern HVFState *hvf_state;
|
||||||
|
|
||||||
struct AccelCPUState {
|
struct AccelCPUState {
|
||||||
uint64_t fd;
|
hvf_vcpuid fd;
|
||||||
void *exit;
|
void *exit;
|
||||||
bool vtimer_masked;
|
bool vtimer_masked;
|
||||||
sigset_t unblock_ipi_mask;
|
sigset_t unblock_ipi_mask;
|
||||||
@ -58,7 +60,10 @@ struct AccelCPUState {
|
|||||||
bool dirty;
|
bool dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
void assert_hvf_ok(hv_return_t ret);
|
void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
|
||||||
|
const char *exp);
|
||||||
|
#define assert_hvf_ok(EX) assert_hvf_ok_impl((EX), __FILE__, __LINE__, #EX)
|
||||||
|
const char *hvf_return_string(hv_return_t ret);
|
||||||
int hvf_arch_init(void);
|
int hvf_arch_init(void);
|
||||||
int hvf_arch_init_vcpu(CPUState *cpu);
|
int hvf_arch_init_vcpu(CPUState *cpu);
|
||||||
void hvf_arch_vcpu_destroy(CPUState *cpu);
|
void hvf_arch_vcpu_destroy(CPUState *cpu);
|
||||||
|
14
meson.build
14
meson.build
@ -2556,10 +2556,16 @@ config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
|
|||||||
#else
|
#else
|
||||||
int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
|
int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
|
||||||
#endif'''))
|
#endif'''))
|
||||||
config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
|
|
||||||
#include <sys/mman.h>
|
# On Darwin posix_madvise() has the same return semantics as plain madvise(),
|
||||||
#include <stddef.h>
|
# i.e. errno is set and -1 is returned. That's not really how POSIX defines the
|
||||||
int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
|
# function. On the flip side, it has madvise() which is preferred anyways.
|
||||||
|
if host_os != 'darwin'
|
||||||
|
config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
|
||||||
|
endif
|
||||||
|
|
||||||
config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
|
config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -13,7 +13,6 @@ Commands:
|
|||||||
create create a venv
|
create create a venv
|
||||||
post_init
|
post_init
|
||||||
post-venv initialization
|
post-venv initialization
|
||||||
ensure Ensure that the specified package is installed.
|
|
||||||
ensuregroup
|
ensuregroup
|
||||||
Ensure that the specified package group is installed.
|
Ensure that the specified package group is installed.
|
||||||
|
|
||||||
@ -36,18 +35,6 @@ options:
|
|||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
usage: mkvenv ensure [-h] [--online] [--dir DIR] dep_spec...
|
|
||||||
|
|
||||||
positional arguments:
|
|
||||||
dep_spec PEP 508 Dependency specification, e.g. 'meson>=0.61.5'
|
|
||||||
|
|
||||||
options:
|
|
||||||
-h, --help show this help message and exit
|
|
||||||
--online Install packages from PyPI, if necessary.
|
|
||||||
--dir DIR Path to vendored packages where we may install from.
|
|
||||||
|
|
||||||
--------------------------------------------------
|
|
||||||
|
|
||||||
usage: mkvenv ensuregroup [-h] [--online] [--dir DIR] file group...
|
usage: mkvenv ensuregroup [-h] [--online] [--dir DIR] file group...
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
@ -726,57 +713,6 @@ def _do_ensure(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def ensure(
|
|
||||||
dep_specs: Sequence[str],
|
|
||||||
online: bool = False,
|
|
||||||
wheels_dir: Optional[Union[str, Path]] = None,
|
|
||||||
prog: Optional[str] = None,
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Use pip to ensure we have the package specified by @dep_specs.
|
|
||||||
|
|
||||||
If the package is already installed, do nothing. If online and
|
|
||||||
wheels_dir are both provided, prefer packages found in wheels_dir
|
|
||||||
first before connecting to PyPI.
|
|
||||||
|
|
||||||
:param dep_specs:
|
|
||||||
PEP 508 dependency specifications. e.g. ['meson>=0.61.5'].
|
|
||||||
:param online: If True, fall back to PyPI.
|
|
||||||
:param wheels_dir: If specified, search this path for packages.
|
|
||||||
:param prog:
|
|
||||||
If specified, use this program name for error diagnostics that will
|
|
||||||
be presented to the user. e.g., 'sphinx-build' can be used as a
|
|
||||||
bellwether for the presence of 'sphinx'.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not HAVE_DISTLIB:
|
|
||||||
raise Ouch("a usable distlib could not be found, please install it")
|
|
||||||
|
|
||||||
# Convert the depspecs to a dictionary, as if they came
|
|
||||||
# from a section in a pythondeps.toml file
|
|
||||||
group: Dict[str, Dict[str, str]] = {}
|
|
||||||
for spec in dep_specs:
|
|
||||||
name = distlib.version.LegacyMatcher(spec).name
|
|
||||||
group[name] = {}
|
|
||||||
|
|
||||||
spec = spec.strip()
|
|
||||||
pos = len(name)
|
|
||||||
ver = spec[pos:].strip()
|
|
||||||
if ver:
|
|
||||||
group[name]["accepted"] = ver
|
|
||||||
|
|
||||||
if prog:
|
|
||||||
group[name]["canary"] = prog
|
|
||||||
prog = None
|
|
||||||
|
|
||||||
result = _do_ensure(group, online, wheels_dir)
|
|
||||||
if result:
|
|
||||||
# Well, that's not good.
|
|
||||||
if result[1]:
|
|
||||||
raise Ouch(result[0])
|
|
||||||
raise SystemExit(f"\n{result[0]}\n\n")
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_groups(file: str) -> Dict[str, Dict[str, Any]]:
|
def _parse_groups(file: str) -> Dict[str, Dict[str, Any]]:
|
||||||
if not HAVE_TOMLLIB:
|
if not HAVE_TOMLLIB:
|
||||||
if sys.version_info < (3, 11):
|
if sys.version_info < (3, 11):
|
||||||
@ -888,39 +824,6 @@ def _add_ensuregroup_subcommand(subparsers: Any) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _add_ensure_subcommand(subparsers: Any) -> None:
|
|
||||||
subparser = subparsers.add_parser(
|
|
||||||
"ensure", help="Ensure that the specified package is installed."
|
|
||||||
)
|
|
||||||
subparser.add_argument(
|
|
||||||
"--online",
|
|
||||||
action="store_true",
|
|
||||||
help="Install packages from PyPI, if necessary.",
|
|
||||||
)
|
|
||||||
subparser.add_argument(
|
|
||||||
"--dir",
|
|
||||||
type=str,
|
|
||||||
action="store",
|
|
||||||
help="Path to vendored packages where we may install from.",
|
|
||||||
)
|
|
||||||
subparser.add_argument(
|
|
||||||
"--diagnose",
|
|
||||||
type=str,
|
|
||||||
action="store",
|
|
||||||
help=(
|
|
||||||
"Name of a shell utility to use for "
|
|
||||||
"diagnostics if this command fails."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
subparser.add_argument(
|
|
||||||
"dep_specs",
|
|
||||||
type=str,
|
|
||||||
action="store",
|
|
||||||
help="PEP 508 Dependency specification, e.g. 'meson>=0.61.5'",
|
|
||||||
nargs="+",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
"""CLI interface to make_qemu_venv. See module docstring."""
|
"""CLI interface to make_qemu_venv. See module docstring."""
|
||||||
if os.environ.get("DEBUG") or os.environ.get("GITLAB_CI"):
|
if os.environ.get("DEBUG") or os.environ.get("GITLAB_CI"):
|
||||||
@ -944,7 +847,6 @@ def main() -> int:
|
|||||||
|
|
||||||
_add_create_subcommand(subparsers)
|
_add_create_subcommand(subparsers)
|
||||||
_add_post_init_subcommand(subparsers)
|
_add_post_init_subcommand(subparsers)
|
||||||
_add_ensure_subcommand(subparsers)
|
|
||||||
_add_ensuregroup_subcommand(subparsers)
|
_add_ensuregroup_subcommand(subparsers)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@ -957,13 +859,6 @@ def main() -> int:
|
|||||||
)
|
)
|
||||||
if args.command == "post_init":
|
if args.command == "post_init":
|
||||||
post_venv_setup()
|
post_venv_setup()
|
||||||
if args.command == "ensure":
|
|
||||||
ensure(
|
|
||||||
dep_specs=args.dep_specs,
|
|
||||||
online=args.online,
|
|
||||||
wheels_dir=args.dir,
|
|
||||||
prog=args.diagnose,
|
|
||||||
)
|
|
||||||
if args.command == "ensuregroup":
|
if args.command == "ensuregroup":
|
||||||
ensure_group(
|
ensure_group(
|
||||||
file=args.file,
|
file=args.file,
|
||||||
|
@ -43,9 +43,6 @@ def main() -> int:
|
|||||||
packages = {
|
packages = {
|
||||||
"meson==1.2.3":
|
"meson==1.2.3":
|
||||||
"4533a43c34548edd1f63a276a42690fce15bde9409bcf20c4b8fa3d7e4d7cac1",
|
"4533a43c34548edd1f63a276a42690fce15bde9409bcf20c4b8fa3d7e4d7cac1",
|
||||||
|
|
||||||
"tomli==2.0.1":
|
|
||||||
"939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vendor_dir = Path(__file__, "..", "..", "wheels").resolve()
|
vendor_dir = Path(__file__, "..", "..", "wheels").resolve()
|
||||||
|
Binary file not shown.
@ -24,6 +24,7 @@ MSR_IA32_VMX_TRUE_EXIT_CTLS = 0x48F
|
|||||||
MSR_IA32_VMX_TRUE_ENTRY_CTLS = 0x490
|
MSR_IA32_VMX_TRUE_ENTRY_CTLS = 0x490
|
||||||
MSR_IA32_VMX_VMFUNC = 0x491
|
MSR_IA32_VMX_VMFUNC = 0x491
|
||||||
MSR_IA32_VMX_PROCBASED_CTLS3 = 0x492
|
MSR_IA32_VMX_PROCBASED_CTLS3 = 0x492
|
||||||
|
MSR_IA32_VMX_EXIT_CTLS2 = 0x493
|
||||||
|
|
||||||
class msr(object):
|
class msr(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -116,6 +117,7 @@ controls = [
|
|||||||
54: 'INS/OUTS instruction information',
|
54: 'INS/OUTS instruction information',
|
||||||
55: 'IA32_VMX_TRUE_*_CTLS support',
|
55: 'IA32_VMX_TRUE_*_CTLS support',
|
||||||
56: 'Skip checks on event error code',
|
56: 'Skip checks on event error code',
|
||||||
|
58: 'VMX nested exception support',
|
||||||
},
|
},
|
||||||
msr = MSR_IA32_VMX_BASIC,
|
msr = MSR_IA32_VMX_BASIC,
|
||||||
),
|
),
|
||||||
@ -219,11 +221,21 @@ controls = [
|
|||||||
23: 'Clear IA32_BNDCFGS',
|
23: 'Clear IA32_BNDCFGS',
|
||||||
24: 'Conceal VM exits from PT',
|
24: 'Conceal VM exits from PT',
|
||||||
25: 'Clear IA32_RTIT_CTL',
|
25: 'Clear IA32_RTIT_CTL',
|
||||||
|
31: 'Activate secondary VM-exit controls',
|
||||||
},
|
},
|
||||||
cap_msr = MSR_IA32_VMX_EXIT_CTLS,
|
cap_msr = MSR_IA32_VMX_EXIT_CTLS,
|
||||||
true_cap_msr = MSR_IA32_VMX_TRUE_EXIT_CTLS,
|
true_cap_msr = MSR_IA32_VMX_TRUE_EXIT_CTLS,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
Allowed1Control(
|
||||||
|
name = 'secondary VM-Exit controls',
|
||||||
|
bits = {
|
||||||
|
0: 'Save IA32 FRED MSRs',
|
||||||
|
1: 'Load IA32 FRED MSRs',
|
||||||
|
},
|
||||||
|
cap_msr = MSR_IA32_VMX_EXIT_CTLS2,
|
||||||
|
),
|
||||||
|
|
||||||
Control(
|
Control(
|
||||||
name = 'VM-Entry controls',
|
name = 'VM-Entry controls',
|
||||||
bits = {
|
bits = {
|
||||||
@ -237,6 +249,7 @@ controls = [
|
|||||||
16: 'Load IA32_BNDCFGS',
|
16: 'Load IA32_BNDCFGS',
|
||||||
17: 'Conceal VM entries from PT',
|
17: 'Conceal VM entries from PT',
|
||||||
18: 'Load IA32_RTIT_CTL',
|
18: 'Load IA32_RTIT_CTL',
|
||||||
|
23: 'Load IA32 FRED MSRs',
|
||||||
},
|
},
|
||||||
cap_msr = MSR_IA32_VMX_ENTRY_CTLS,
|
cap_msr = MSR_IA32_VMX_ENTRY_CTLS,
|
||||||
true_cap_msr = MSR_IA32_VMX_TRUE_ENTRY_CTLS,
|
true_cap_msr = MSR_IA32_VMX_TRUE_ENTRY_CTLS,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
# below, so that it is clear who needs the stubbed functionality.
|
# below, so that it is clear who needs the stubbed functionality.
|
||||||
|
|
||||||
stub_ss.add(files('cpu-get-clock.c'))
|
stub_ss.add(files('cpu-get-clock.c'))
|
||||||
|
stub_ss.add(files('error-printf.c'))
|
||||||
stub_ss.add(files('fdset.c'))
|
stub_ss.add(files('fdset.c'))
|
||||||
stub_ss.add(files('iothread-lock.c'))
|
stub_ss.add(files('iothread-lock.c'))
|
||||||
stub_ss.add(files('is-daemonized.c'))
|
stub_ss.add(files('is-daemonized.c'))
|
||||||
@ -45,17 +46,10 @@ if have_block or have_ga
|
|||||||
stub_ss.add(files('qmp-quit.c'))
|
stub_ss.add(files('qmp-quit.c'))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if have_ga
|
|
||||||
stub_ss.add(files('error-printf.c'))
|
|
||||||
endif
|
|
||||||
|
|
||||||
if have_block or have_user
|
if have_block or have_user
|
||||||
stub_ss.add(files('qtest.c'))
|
stub_ss.add(files('qtest.c'))
|
||||||
stub_ss.add(files('vm-stop.c'))
|
stub_ss.add(files('vm-stop.c'))
|
||||||
stub_ss.add(files('vmstate.c'))
|
stub_ss.add(files('vmstate.c'))
|
||||||
|
|
||||||
# more symbols provided by the monitor
|
|
||||||
stub_ss.add(files('error-printf.c'))
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if have_user
|
if have_user
|
||||||
|
@ -1114,7 +1114,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||||||
"avx-vnni", "avx512-bf16", NULL, "cmpccxadd",
|
"avx-vnni", "avx512-bf16", NULL, "cmpccxadd",
|
||||||
NULL, NULL, "fzrm", "fsrs",
|
NULL, NULL, "fzrm", "fsrs",
|
||||||
"fsrc", NULL, NULL, NULL,
|
"fsrc", NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, "fred", "lkgs", "wrmsrns",
|
||||||
NULL, "amx-fp16", NULL, "avx-ifma",
|
NULL, "amx-fp16", NULL, "avx-ifma",
|
||||||
NULL, NULL, "lam", NULL,
|
NULL, NULL, "lam", NULL,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
@ -1180,6 +1180,22 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||||||
.tcg_features = TCG_APM_FEATURES,
|
.tcg_features = TCG_APM_FEATURES,
|
||||||
.unmigratable_flags = CPUID_APM_INVTSC,
|
.unmigratable_flags = CPUID_APM_INVTSC,
|
||||||
},
|
},
|
||||||
|
[FEAT_8000_0007_EBX] = {
|
||||||
|
.type = CPUID_FEATURE_WORD,
|
||||||
|
.feat_names = {
|
||||||
|
"overflow-recov", "succor", NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
},
|
||||||
|
.cpuid = { .eax = 0x80000007, .reg = R_EBX, },
|
||||||
|
.tcg_features = 0,
|
||||||
|
.unmigratable_flags = 0,
|
||||||
|
},
|
||||||
[FEAT_8000_0008_EBX] = {
|
[FEAT_8000_0008_EBX] = {
|
||||||
.type = CPUID_FEATURE_WORD,
|
.type = CPUID_FEATURE_WORD,
|
||||||
.feat_names = {
|
.feat_names = {
|
||||||
@ -1492,6 +1508,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||||||
[54] = "vmx-ins-outs",
|
[54] = "vmx-ins-outs",
|
||||||
[55] = "vmx-true-ctls",
|
[55] = "vmx-true-ctls",
|
||||||
[56] = "vmx-any-errcode",
|
[56] = "vmx-any-errcode",
|
||||||
|
[58] = "vmx-nested-exception",
|
||||||
},
|
},
|
||||||
.msr = {
|
.msr = {
|
||||||
.index = MSR_IA32_VMX_BASIC,
|
.index = MSR_IA32_VMX_BASIC,
|
||||||
@ -1701,6 +1718,18 @@ static FeatureDep feature_dependencies[] = {
|
|||||||
.from = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
|
.from = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
|
||||||
.to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
|
.to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.from = { FEAT_8000_0001_EDX, CPUID_EXT2_LM },
|
||||||
|
.to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.from = { FEAT_7_1_EAX, CPUID_7_1_EAX_LKGS },
|
||||||
|
.to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.from = { FEAT_7_1_EAX, CPUID_7_1_EAX_WRMSRNS },
|
||||||
|
.to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct X86RegisterInfo32 {
|
typedef struct X86RegisterInfo32 {
|
||||||
@ -6874,7 +6903,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||||||
break;
|
break;
|
||||||
case 0x80000007:
|
case 0x80000007:
|
||||||
*eax = 0;
|
*eax = 0;
|
||||||
*ebx = 0;
|
*ebx = env->features[FEAT_8000_0007_EBX];
|
||||||
*ecx = 0;
|
*ecx = 0;
|
||||||
*edx = env->features[FEAT_8000_0007_EDX];
|
*edx = env->features[FEAT_8000_0007_EDX];
|
||||||
break;
|
break;
|
||||||
|
@ -261,6 +261,18 @@ typedef enum X86Seg {
|
|||||||
#define CR4_PKS_MASK (1U << 24)
|
#define CR4_PKS_MASK (1U << 24)
|
||||||
#define CR4_LAM_SUP_MASK (1U << 28)
|
#define CR4_LAM_SUP_MASK (1U << 28)
|
||||||
|
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
#define CR4_FRED_MASK (1ULL << 32)
|
||||||
|
#else
|
||||||
|
#define CR4_FRED_MASK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
#define CR4_FRED_MASK (1ULL << 32)
|
||||||
|
#else
|
||||||
|
#define CR4_FRED_MASK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CR4_RESERVED_MASK \
|
#define CR4_RESERVED_MASK \
|
||||||
(~(target_ulong)(CR4_VME_MASK | CR4_PVI_MASK | CR4_TSD_MASK \
|
(~(target_ulong)(CR4_VME_MASK | CR4_PVI_MASK | CR4_TSD_MASK \
|
||||||
| CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \
|
| CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \
|
||||||
@ -269,7 +281,7 @@ typedef enum X86Seg {
|
|||||||
| CR4_LA57_MASK \
|
| CR4_LA57_MASK \
|
||||||
| CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \
|
| CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \
|
||||||
| CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK \
|
| CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK \
|
||||||
| CR4_LAM_SUP_MASK))
|
| CR4_LAM_SUP_MASK | CR4_FRED_MASK))
|
||||||
|
|
||||||
#define DR6_BD (1 << 13)
|
#define DR6_BD (1 << 13)
|
||||||
#define DR6_BS (1 << 14)
|
#define DR6_BS (1 << 14)
|
||||||
@ -365,6 +377,8 @@ typedef enum X86Seg {
|
|||||||
#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */
|
#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */
|
||||||
#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
|
#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
|
||||||
#define MCI_STATUS_AR (1ULL<<55) /* Action required */
|
#define MCI_STATUS_AR (1ULL<<55) /* Action required */
|
||||||
|
#define MCI_STATUS_DEFERRED (1ULL<<44) /* Deferred error */
|
||||||
|
#define MCI_STATUS_POISON (1ULL<<43) /* Poisoned data consumed */
|
||||||
|
|
||||||
/* MISC register defines */
|
/* MISC register defines */
|
||||||
#define MCM_ADDR_SEGOFF 0 /* segment offset */
|
#define MCM_ADDR_SEGOFF 0 /* segment offset */
|
||||||
@ -526,6 +540,17 @@ typedef enum X86Seg {
|
|||||||
#define MSR_IA32_XFD 0x000001c4
|
#define MSR_IA32_XFD 0x000001c4
|
||||||
#define MSR_IA32_XFD_ERR 0x000001c5
|
#define MSR_IA32_XFD_ERR 0x000001c5
|
||||||
|
|
||||||
|
/* FRED MSRs */
|
||||||
|
#define MSR_IA32_FRED_RSP0 0x000001cc /* Stack level 0 regular stack pointer */
|
||||||
|
#define MSR_IA32_FRED_RSP1 0x000001cd /* Stack level 1 regular stack pointer */
|
||||||
|
#define MSR_IA32_FRED_RSP2 0x000001ce /* Stack level 2 regular stack pointer */
|
||||||
|
#define MSR_IA32_FRED_RSP3 0x000001cf /* Stack level 3 regular stack pointer */
|
||||||
|
#define MSR_IA32_FRED_STKLVLS 0x000001d0 /* FRED exception stack levels */
|
||||||
|
#define MSR_IA32_FRED_SSP1 0x000001d1 /* Stack level 1 shadow stack pointer in ring 0 */
|
||||||
|
#define MSR_IA32_FRED_SSP2 0x000001d2 /* Stack level 2 shadow stack pointer in ring 0 */
|
||||||
|
#define MSR_IA32_FRED_SSP3 0x000001d3 /* Stack level 3 shadow stack pointer in ring 0 */
|
||||||
|
#define MSR_IA32_FRED_CONFIG 0x000001d4 /* FRED Entrypoint and interrupt stack level */
|
||||||
|
|
||||||
#define MSR_IA32_BNDCFGS 0x00000d90
|
#define MSR_IA32_BNDCFGS 0x00000d90
|
||||||
#define MSR_IA32_XSS 0x00000da0
|
#define MSR_IA32_XSS 0x00000da0
|
||||||
#define MSR_IA32_UMWAIT_CONTROL 0xe1
|
#define MSR_IA32_UMWAIT_CONTROL 0xe1
|
||||||
@ -605,6 +630,7 @@ typedef enum FeatureWord {
|
|||||||
FEAT_7_1_EAX, /* CPUID[EAX=7,ECX=1].EAX */
|
FEAT_7_1_EAX, /* CPUID[EAX=7,ECX=1].EAX */
|
||||||
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
|
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
|
||||||
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
|
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
|
||||||
|
FEAT_8000_0007_EBX, /* CPUID[8000_0007].EBX */
|
||||||
FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
|
FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
|
||||||
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
|
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
|
||||||
FEAT_8000_0021_EAX, /* CPUID[8000_0021].EAX */
|
FEAT_8000_0021_EAX, /* CPUID[8000_0021].EAX */
|
||||||
@ -941,6 +967,12 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
|||||||
#define CPUID_7_1_EDX_AMX_COMPLEX (1U << 8)
|
#define CPUID_7_1_EDX_AMX_COMPLEX (1U << 8)
|
||||||
/* PREFETCHIT0/1 Instructions */
|
/* PREFETCHIT0/1 Instructions */
|
||||||
#define CPUID_7_1_EDX_PREFETCHITI (1U << 14)
|
#define CPUID_7_1_EDX_PREFETCHITI (1U << 14)
|
||||||
|
/* Flexible return and event delivery (FRED) */
|
||||||
|
#define CPUID_7_1_EAX_FRED (1U << 17)
|
||||||
|
/* Load into IA32_KERNEL_GS_BASE (LKGS) */
|
||||||
|
#define CPUID_7_1_EAX_LKGS (1U << 18)
|
||||||
|
/* Non-Serializing Write to Model Specific Register (WRMSRNS) */
|
||||||
|
#define CPUID_7_1_EAX_WRMSRNS (1U << 19)
|
||||||
|
|
||||||
/* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */
|
/* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */
|
||||||
#define CPUID_7_2_EDX_MCDT_NO (1U << 5)
|
#define CPUID_7_2_EDX_MCDT_NO (1U << 5)
|
||||||
@ -951,6 +983,10 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
|||||||
/* Packets which contain IP payload have LIP values */
|
/* Packets which contain IP payload have LIP values */
|
||||||
#define CPUID_14_0_ECX_LIP (1U << 31)
|
#define CPUID_14_0_ECX_LIP (1U << 31)
|
||||||
|
|
||||||
|
/* RAS Features */
|
||||||
|
#define CPUID_8000_0007_EBX_OVERFLOW_RECOV (1U << 0)
|
||||||
|
#define CPUID_8000_0007_EBX_SUCCOR (1U << 1)
|
||||||
|
|
||||||
/* CLZERO instruction */
|
/* CLZERO instruction */
|
||||||
#define CPUID_8000_0008_EBX_CLZERO (1U << 0)
|
#define CPUID_8000_0008_EBX_CLZERO (1U << 0)
|
||||||
/* Always save/restore FP error pointers */
|
/* Always save/restore FP error pointers */
|
||||||
@ -1053,6 +1089,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
|||||||
#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54)
|
#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54)
|
||||||
#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55)
|
#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55)
|
||||||
#define MSR_VMX_BASIC_ANY_ERRCODE (1ULL << 56)
|
#define MSR_VMX_BASIC_ANY_ERRCODE (1ULL << 56)
|
||||||
|
#define MSR_VMX_BASIC_NESTED_EXCEPTION (1ULL << 58)
|
||||||
|
|
||||||
#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full
|
#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full
|
||||||
#define MSR_VMX_MISC_STORE_LMA (1ULL << 5)
|
#define MSR_VMX_MISC_STORE_LMA (1ULL << 5)
|
||||||
@ -1704,6 +1741,17 @@ typedef struct CPUArchState {
|
|||||||
target_ulong cstar;
|
target_ulong cstar;
|
||||||
target_ulong fmask;
|
target_ulong fmask;
|
||||||
target_ulong kernelgsbase;
|
target_ulong kernelgsbase;
|
||||||
|
|
||||||
|
/* FRED MSRs */
|
||||||
|
uint64_t fred_rsp0;
|
||||||
|
uint64_t fred_rsp1;
|
||||||
|
uint64_t fred_rsp2;
|
||||||
|
uint64_t fred_rsp3;
|
||||||
|
uint64_t fred_stklvls;
|
||||||
|
uint64_t fred_ssp1;
|
||||||
|
uint64_t fred_ssp2;
|
||||||
|
uint64_t fred_ssp3;
|
||||||
|
uint64_t fred_config;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint64_t tsc_adjust;
|
uint64_t tsc_adjust;
|
||||||
@ -2607,6 +2655,9 @@ static inline uint64_t cr4_reserved_bits(CPUX86State *env)
|
|||||||
if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_LAM)) {
|
if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_LAM)) {
|
||||||
reserved_bits |= CR4_LAM_SUP_MASK;
|
reserved_bits |= CR4_LAM_SUP_MASK;
|
||||||
}
|
}
|
||||||
|
if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED)) {
|
||||||
|
reserved_bits |= CR4_FRED_MASK;
|
||||||
|
}
|
||||||
return reserved_bits;
|
return reserved_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,10 @@ int cpu_x86_support_mca_broadcast(CPUX86State *env)
|
|||||||
int family = 0;
|
int family = 0;
|
||||||
int model = 0;
|
int model = 0;
|
||||||
|
|
||||||
|
if (IS_AMD_CPU(env)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_x86_version(env, &family, &model);
|
cpu_x86_version(env, &family, &model);
|
||||||
if ((family == 6 && model >= 14) || family > 6) {
|
if ((family == 6 && model >= 14) || family > 6) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -53,9 +53,10 @@ DEF_HELPER_1(sysenter, void, env)
|
|||||||
DEF_HELPER_2(sysexit, void, env, int)
|
DEF_HELPER_2(sysexit, void, env, int)
|
||||||
DEF_HELPER_2(syscall, void, env, int)
|
DEF_HELPER_2(syscall, void, env, int)
|
||||||
DEF_HELPER_2(sysret, void, env, int)
|
DEF_HELPER_2(sysret, void, env, int)
|
||||||
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
|
DEF_HELPER_FLAGS_1(pause, TCG_CALL_NO_WG, noreturn, env)
|
||||||
DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
|
DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
|
||||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
|
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
|
||||||
|
DEF_HELPER_FLAGS_1(icebp, TCG_CALL_NO_WG, noreturn, env)
|
||||||
DEF_HELPER_3(boundw, void, env, tl, int)
|
DEF_HELPER_3(boundw, void, env, tl, int)
|
||||||
DEF_HELPER_3(boundl, void, env, tl, int)
|
DEF_HELPER_3(boundl, void, env, tl, int)
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ DEF_HELPER_2(vmsave, void, env, int)
|
|||||||
DEF_HELPER_1(stgi, void, env)
|
DEF_HELPER_1(stgi, void, env)
|
||||||
DEF_HELPER_1(clgi, void, env)
|
DEF_HELPER_1(clgi, void, env)
|
||||||
DEF_HELPER_FLAGS_2(flush_page, TCG_CALL_NO_RWG, void, env, tl)
|
DEF_HELPER_FLAGS_2(flush_page, TCG_CALL_NO_RWG, void, env, tl)
|
||||||
DEF_HELPER_FLAGS_2(hlt, TCG_CALL_NO_WG, noreturn, env, int)
|
DEF_HELPER_FLAGS_1(hlt, TCG_CALL_NO_WG, noreturn, env)
|
||||||
DEF_HELPER_FLAGS_2(monitor, TCG_CALL_NO_WG, void, env, tl)
|
DEF_HELPER_FLAGS_2(monitor, TCG_CALL_NO_WG, void, env, tl)
|
||||||
DEF_HELPER_FLAGS_2(mwait, TCG_CALL_NO_WG, noreturn, env, int)
|
DEF_HELPER_FLAGS_2(mwait, TCG_CALL_NO_WG, noreturn, env, int)
|
||||||
DEF_HELPER_1(rdmsr, void, env)
|
DEF_HELPER_1(rdmsr, void, env)
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/memalign.h"
|
#include "qemu/memalign.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "migration/blocker.h"
|
||||||
|
|
||||||
#include "sysemu/hvf.h"
|
#include "sysemu/hvf.h"
|
||||||
#include "sysemu/hvf_int.h"
|
#include "sysemu/hvf_int.h"
|
||||||
@ -74,6 +76,8 @@
|
|||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "target/i386/cpu.h"
|
#include "target/i386/cpu.h"
|
||||||
|
|
||||||
|
static Error *invtsc_mig_blocker;
|
||||||
|
|
||||||
void vmx_update_tpr(CPUState *cpu)
|
void vmx_update_tpr(CPUState *cpu)
|
||||||
{
|
{
|
||||||
/* TODO: need integrate APIC handling */
|
/* TODO: need integrate APIC handling */
|
||||||
@ -131,9 +135,10 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
|
|||||||
|
|
||||||
if (write && slot) {
|
if (write && slot) {
|
||||||
if (slot->flags & HVF_SLOT_LOG) {
|
if (slot->flags & HVF_SLOT_LOG) {
|
||||||
|
uint64_t dirty_page_start = gpa & ~(TARGET_PAGE_SIZE - 1u);
|
||||||
memory_region_set_dirty(slot->region, gpa - slot->start, 1);
|
memory_region_set_dirty(slot->region, gpa - slot->start, 1);
|
||||||
hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size,
|
hv_vm_protect(dirty_page_start, TARGET_PAGE_SIZE,
|
||||||
HV_MEMORY_READ | HV_MEMORY_WRITE);
|
HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +215,7 @@ static inline bool apic_bus_freq_is_known(CPUX86State *env)
|
|||||||
void hvf_kick_vcpu_thread(CPUState *cpu)
|
void hvf_kick_vcpu_thread(CPUState *cpu)
|
||||||
{
|
{
|
||||||
cpus_kick_thread(cpu);
|
cpus_kick_thread(cpu);
|
||||||
|
hv_vcpu_interrupt(&cpu->accel->fd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hvf_arch_init(void)
|
int hvf_arch_init(void)
|
||||||
@ -221,6 +227,8 @@ int hvf_arch_init_vcpu(CPUState *cpu)
|
|||||||
{
|
{
|
||||||
X86CPU *x86cpu = X86_CPU(cpu);
|
X86CPU *x86cpu = X86_CPU(cpu);
|
||||||
CPUX86State *env = &x86cpu->env;
|
CPUX86State *env = &x86cpu->env;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int r;
|
||||||
uint64_t reqCap;
|
uint64_t reqCap;
|
||||||
|
|
||||||
init_emu();
|
init_emu();
|
||||||
@ -238,6 +246,18 @@ int hvf_arch_init_vcpu(CPUState *cpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC) &&
|
||||||
|
invtsc_mig_blocker == NULL) {
|
||||||
|
error_setg(&invtsc_mig_blocker,
|
||||||
|
"State blocked by non-migratable CPU device (invtsc flag)");
|
||||||
|
r = migrate_add_blocker(&invtsc_mig_blocker, &local_err);
|
||||||
|
if (r < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (hv_vmx_read_capability(HV_VMX_CAP_PINBASED,
|
if (hv_vmx_read_capability(HV_VMX_CAP_PINBASED,
|
||||||
&hvf_state->hvf_caps->vmx_cap_pinbased)) {
|
&hvf_state->hvf_caps->vmx_cap_pinbased)) {
|
||||||
abort();
|
abort();
|
||||||
@ -407,6 +427,27 @@ static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hv_return_t hvf_vcpu_run(hv_vcpuid_t vcpu_id)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* hv_vcpu_run_until is available and recommended from macOS 10.15+,
|
||||||
|
* HV_DEADLINE_FOREVER from 11.0. Test for availability at runtime and fall
|
||||||
|
* back to hv_vcpu_run() only where necessary.
|
||||||
|
*/
|
||||||
|
#ifndef MAC_OS_VERSION_11_0
|
||||||
|
return hv_vcpu_run(vcpu_id);
|
||||||
|
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
||||||
|
return hv_vcpu_run_until(vcpu_id, HV_DEADLINE_FOREVER);
|
||||||
|
#else /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0 */
|
||||||
|
/* 11.0 SDK or newer, but could be < 11 at runtime */
|
||||||
|
if (__builtin_available(macOS 11.0, *)) {
|
||||||
|
return hv_vcpu_run_until(vcpu_id, HV_DEADLINE_FOREVER);
|
||||||
|
} else {
|
||||||
|
return hv_vcpu_run(vcpu_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int hvf_vcpu_exec(CPUState *cpu)
|
int hvf_vcpu_exec(CPUState *cpu)
|
||||||
{
|
{
|
||||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||||
@ -435,7 +476,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
|||||||
return EXCP_HLT;
|
return EXCP_HLT;
|
||||||
}
|
}
|
||||||
|
|
||||||
hv_return_t r = hv_vcpu_run(cpu->accel->fd);
|
hv_return_t r = hvf_vcpu_run(cpu->accel->fd);
|
||||||
assert_hvf_ok(r);
|
assert_hvf_ok(r);
|
||||||
|
|
||||||
/* handle VMEXIT */
|
/* handle VMEXIT */
|
||||||
|
@ -95,8 +95,7 @@ static void enter_long_mode(hv_vcpuid_t vcpu, uint64_t cr0, uint64_t efer)
|
|||||||
efer |= MSR_EFER_LMA;
|
efer |= MSR_EFER_LMA;
|
||||||
wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer);
|
wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer);
|
||||||
entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS);
|
entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS);
|
||||||
wvmcs(vcpu, VMCS_ENTRY_CTLS, rvmcs(vcpu, VMCS_ENTRY_CTLS) |
|
wvmcs(vcpu, VMCS_ENTRY_CTLS, entry_ctls | VM_ENTRY_GUEST_LMA);
|
||||||
VM_ENTRY_GUEST_LMA);
|
|
||||||
|
|
||||||
uint64_t guest_tr_ar = rvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS);
|
uint64_t guest_tr_ar = rvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS);
|
||||||
if ((efer & MSR_EFER_LME) &&
|
if ((efer & MSR_EFER_LME) &&
|
||||||
|
@ -146,6 +146,10 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
|
|||||||
CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
|
CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
|
||||||
CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
|
CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
|
||||||
break;
|
break;
|
||||||
|
case 0x80000007:
|
||||||
|
edx &= CPUID_APM_INVTSC;
|
||||||
|
eax = ebx = ecx = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2111,7 +2111,7 @@ uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode)
|
|||||||
return decode->len;
|
return decode->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_decoder()
|
void init_decoder(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1409,7 +1409,7 @@ static struct cmd_handler {
|
|||||||
|
|
||||||
static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
|
static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
|
||||||
|
|
||||||
static void init_cmd_handler()
|
static void init_cmd_handler(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
|
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
|
||||||
@ -1481,7 +1481,7 @@ bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_emu()
|
void init_emu(void)
|
||||||
{
|
{
|
||||||
init_cmd_handler();
|
init_cmd_handler();
|
||||||
}
|
}
|
||||||
|
@ -532,6 +532,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
|
|||||||
*/
|
*/
|
||||||
cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
|
cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
|
||||||
ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES;
|
ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES;
|
||||||
|
} else if (function == 0x80000007 && reg == R_EBX) {
|
||||||
|
ret |= CPUID_8000_0007_EBX_OVERFLOW_RECOV | CPUID_8000_0007_EBX_SUCCOR;
|
||||||
} else if (function == KVM_CPUID_FEATURES && reg == R_EAX) {
|
} else if (function == KVM_CPUID_FEATURES && reg == R_EAX) {
|
||||||
/* kvm_pv_unhalt is reported by GET_SUPPORTED_CPUID, but it can't
|
/* kvm_pv_unhalt is reported by GET_SUPPORTED_CPUID, but it can't
|
||||||
* be enabled without the in-kernel irqchip
|
* be enabled without the in-kernel irqchip
|
||||||
@ -638,17 +640,40 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code)
|
|||||||
{
|
{
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
|
uint64_t status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_MISCV |
|
||||||
MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S;
|
MCI_STATUS_ADDRV;
|
||||||
uint64_t mcg_status = MCG_STATUS_MCIP;
|
uint64_t mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
if (code == BUS_MCEERR_AR) {
|
if (!IS_AMD_CPU(env)) {
|
||||||
status |= MCI_STATUS_AR | 0x134;
|
status |= MCI_STATUS_S | MCI_STATUS_UC;
|
||||||
mcg_status |= MCG_STATUS_RIPV | MCG_STATUS_EIPV;
|
if (code == BUS_MCEERR_AR) {
|
||||||
|
status |= MCI_STATUS_AR | 0x134;
|
||||||
|
mcg_status |= MCG_STATUS_EIPV;
|
||||||
|
} else {
|
||||||
|
status |= 0xc0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
status |= 0xc0;
|
if (code == BUS_MCEERR_AR) {
|
||||||
mcg_status |= MCG_STATUS_RIPV;
|
status |= MCI_STATUS_UC | MCI_STATUS_POISON;
|
||||||
|
mcg_status |= MCG_STATUS_EIPV;
|
||||||
|
} else {
|
||||||
|
/* Setting the POISON bit for deferred errors indicates to the
|
||||||
|
* guest kernel that the address provided by the MCE is valid
|
||||||
|
* and usable which will ensure that the guest kernel will send
|
||||||
|
* a SIGBUS_AO signal to the guest process. This allows for
|
||||||
|
* more desirable behavior in the case that the guest process
|
||||||
|
* with poisoned memory has set the MCE_KILL_EARLY prctl flag
|
||||||
|
* which indicates that the process would prefer to handle or
|
||||||
|
* shutdown due to the poisoned memory condition before the
|
||||||
|
* memory has been accessed.
|
||||||
|
*
|
||||||
|
* While the POISON bit would not be set in a deferred error
|
||||||
|
* sent from hardware, the bit is not meaningful for deferred
|
||||||
|
* errors and can be reused in this scenario.
|
||||||
|
*/
|
||||||
|
status |= MCI_STATUS_DEFERRED | MCI_STATUS_POISON;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = cpu_x86_support_mca_broadcast(env) ? MCE_INJECT_BROADCAST : 0;
|
flags = cpu_x86_support_mca_broadcast(env) ? MCE_INJECT_BROADCAST : 0;
|
||||||
@ -3376,6 +3401,17 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
|||||||
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase);
|
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase);
|
||||||
kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask);
|
kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask);
|
||||||
kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
|
kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
|
||||||
|
if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, env->fred_rsp0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, env->fred_rsp1);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, env->fred_rsp2);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, env->fred_rsp3);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, env->fred_stklvls);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, env->fred_ssp1);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, env->fred_ssp2);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, env->fred_ssp3);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, env->fred_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3848,6 +3884,17 @@ static int kvm_get_msrs(X86CPU *cpu)
|
|||||||
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0);
|
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0);
|
||||||
kvm_msr_entry_add(cpu, MSR_FMASK, 0);
|
kvm_msr_entry_add(cpu, MSR_FMASK, 0);
|
||||||
kvm_msr_entry_add(cpu, MSR_LSTAR, 0);
|
kvm_msr_entry_add(cpu, MSR_LSTAR, 0);
|
||||||
|
if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, 0);
|
||||||
|
kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0);
|
kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0);
|
||||||
@ -4069,6 +4116,33 @@ static int kvm_get_msrs(X86CPU *cpu)
|
|||||||
case MSR_LSTAR:
|
case MSR_LSTAR:
|
||||||
env->lstar = msrs[i].data;
|
env->lstar = msrs[i].data;
|
||||||
break;
|
break;
|
||||||
|
case MSR_IA32_FRED_RSP0:
|
||||||
|
env->fred_rsp0 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_RSP1:
|
||||||
|
env->fred_rsp1 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_RSP2:
|
||||||
|
env->fred_rsp2 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_RSP3:
|
||||||
|
env->fred_rsp3 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_STKLVLS:
|
||||||
|
env->fred_stklvls = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_SSP1:
|
||||||
|
env->fred_ssp1 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_SSP2:
|
||||||
|
env->fred_ssp2 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_SSP3:
|
||||||
|
env->fred_ssp3 = msrs[i].data;
|
||||||
|
break;
|
||||||
|
case MSR_IA32_FRED_CONFIG:
|
||||||
|
env->fred_config = msrs[i].data;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MSR_IA32_TSC:
|
case MSR_IA32_TSC:
|
||||||
env->tsc = msrs[i].data;
|
env->tsc = msrs[i].data;
|
||||||
|
@ -1544,6 +1544,33 @@ static const VMStateDescription vmstate_msr_xfd = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
|
static bool intel_fred_msrs_needed(void *opaque)
|
||||||
|
{
|
||||||
|
X86CPU *cpu = opaque;
|
||||||
|
CPUX86State *env = &cpu->env;
|
||||||
|
|
||||||
|
return !!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_msr_fred = {
|
||||||
|
.name = "cpu/fred",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.needed = intel_fred_msrs_needed,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT64(env.fred_rsp0, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_rsp1, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_rsp2, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_rsp3, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_stklvls, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_ssp1, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_ssp2, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_ssp3, X86CPU),
|
||||||
|
VMSTATE_UINT64(env.fred_config, X86CPU),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static bool amx_xtile_needed(void *opaque)
|
static bool amx_xtile_needed(void *opaque)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = opaque;
|
X86CPU *cpu = opaque;
|
||||||
@ -1747,6 +1774,7 @@ const VMStateDescription vmstate_x86_cpu = {
|
|||||||
&vmstate_pdptrs,
|
&vmstate_pdptrs,
|
||||||
&vmstate_msr_xfd,
|
&vmstate_msr_xfd,
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
|
&vmstate_msr_fred,
|
||||||
&vmstate_amx_xtile,
|
&vmstate_amx_xtile,
|
||||||
#endif
|
#endif
|
||||||
&vmstate_arch_lbr,
|
&vmstate_arch_lbr,
|
||||||
|
@ -1359,6 +1359,19 @@ static void decode_group11(DisasContext *s, CPUX86State *env, X86OpEntry *entry,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void decode_90(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
|
||||||
|
{
|
||||||
|
static X86OpEntry pause = X86_OP_ENTRY0(PAUSE, svm(PAUSE));
|
||||||
|
static X86OpEntry nop = X86_OP_ENTRY0(NOP);
|
||||||
|
static X86OpEntry xchg_ax = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v);
|
||||||
|
|
||||||
|
if (REX_B(s)) {
|
||||||
|
*entry = xchg_ax;
|
||||||
|
} else {
|
||||||
|
*entry = (s->prefix & PREFIX_REPZ) ? pause : nop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const X86OpEntry opcodes_root[256] = {
|
static const X86OpEntry opcodes_root[256] = {
|
||||||
[0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock),
|
[0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock),
|
||||||
[0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock),
|
[0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock),
|
||||||
@ -1441,7 +1454,7 @@ static const X86OpEntry opcodes_root[256] = {
|
|||||||
[0x86] = X86_OP_ENTRY2(XCHG, E,b, G,b, xchg),
|
[0x86] = X86_OP_ENTRY2(XCHG, E,b, G,b, xchg),
|
||||||
[0x87] = X86_OP_ENTRY2(XCHG, E,v, G,v, xchg),
|
[0x87] = X86_OP_ENTRY2(XCHG, E,v, G,v, xchg),
|
||||||
|
|
||||||
[0x90] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
[0x90] = X86_OP_GROUP0(90),
|
||||||
[0x91] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
[0x91] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
||||||
[0x92] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
[0x92] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
||||||
[0x93] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
[0x93] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v),
|
||||||
@ -1496,7 +1509,7 @@ static const X86OpEntry opcodes_root[256] = {
|
|||||||
[0xE7] = X86_OP_ENTRYrr(OUT, 0,v, I_unsigned,b), /* AX/EAX */
|
[0xE7] = X86_OP_ENTRYrr(OUT, 0,v, I_unsigned,b), /* AX/EAX */
|
||||||
|
|
||||||
[0xF1] = X86_OP_ENTRY0(INT1, svm(ICEBP)),
|
[0xF1] = X86_OP_ENTRY0(INT1, svm(ICEBP)),
|
||||||
[0xF4] = X86_OP_ENTRY0(HLT, chk(cpl0)),
|
[0xF4] = X86_OP_ENTRY0(HLT, chk(cpl0) svm(HLT)),
|
||||||
[0xF5] = X86_OP_ENTRY0(CMC),
|
[0xF5] = X86_OP_ENTRY0(CMC),
|
||||||
[0xF6] = X86_OP_GROUP1(group3, E,b),
|
[0xF6] = X86_OP_GROUP1(group3, E,b),
|
||||||
[0xF7] = X86_OP_GROUP1(group3, E,v),
|
[0xF7] = X86_OP_GROUP1(group3, E,v),
|
||||||
@ -2539,7 +2552,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks that result in #GP or VMEXIT come second. Intercepts are
|
* Checks that result in #GP or VMEXIT come second. Intercepts are
|
||||||
* generally checked after non-memory exceptions (i.e. before all
|
* generally checked after non-memory exceptions (i.e. after all
|
||||||
* exceptions if there is no memory operand). Exceptions are
|
* exceptions if there is no memory operand). Exceptions are
|
||||||
* vm86 checks (INTn, IRET, PUSHF/POPF), RSM and XSETBV (!).
|
* vm86 checks (INTn, IRET, PUSHF/POPF), RSM and XSETBV (!).
|
||||||
*
|
*
|
||||||
|
@ -1638,8 +1638,8 @@ static void gen_HLT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|||||||
{
|
{
|
||||||
#ifdef CONFIG_SYSTEM_ONLY
|
#ifdef CONFIG_SYSTEM_ONLY
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
gen_update_eip_cur(s);
|
gen_update_eip_next(s);
|
||||||
gen_helper_hlt(tcg_env, cur_insn_len_i32(s));
|
gen_helper_hlt(tcg_env);
|
||||||
s->base.is_jmp = DISAS_NORETURN;
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1858,7 +1858,10 @@ static void gen_INT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|||||||
|
|
||||||
static void gen_INT1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
static void gen_INT1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
{
|
{
|
||||||
gen_exception(s, EXCP01_DB);
|
gen_update_cc_op(s);
|
||||||
|
gen_update_eip_next(s);
|
||||||
|
gen_helper_icebp(tcg_env);
|
||||||
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_INT3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
static void gen_INT3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
@ -2347,6 +2350,14 @@ static void gen_PANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|||||||
decode->op[1].offset, vec_len, vec_len);
|
decode->op[1].offset, vec_len, vec_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_PAUSE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
|
{
|
||||||
|
gen_update_cc_op(s);
|
||||||
|
gen_update_eip_next(s);
|
||||||
|
gen_helper_pause(tcg_env);
|
||||||
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_PCMPESTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
static void gen_PCMPESTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
{
|
{
|
||||||
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
|
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
|
||||||
@ -2564,12 +2575,14 @@ static void gen_PMOVMSKB(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
|
|||||||
|
|
||||||
static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
{
|
{
|
||||||
|
X86DecodedOp *op = &decode->op[0];
|
||||||
MemOp ot = gen_pop_T0(s);
|
MemOp ot = gen_pop_T0(s);
|
||||||
if (decode->op[0].has_ea) {
|
|
||||||
|
if (op->has_ea || op->unit == X86_OP_SEG) {
|
||||||
/* NOTE: order is important for MMU exceptions */
|
/* NOTE: order is important for MMU exceptions */
|
||||||
gen_op_st_v(s, ot, s->T0, s->A0);
|
gen_writeback(s, decode, 0, s->T0);
|
||||||
decode->op[0].unit = X86_OP_SKIP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: writing back registers after update is important for pop %sp */
|
/* NOTE: writing back registers after update is important for pop %sp */
|
||||||
gen_pop_update(s, ot);
|
gen_pop_update(s, ot);
|
||||||
}
|
}
|
||||||
@ -4011,18 +4024,6 @@ static void gen_WAIT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
|||||||
|
|
||||||
static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
|
||||||
{
|
{
|
||||||
if (decode->b == 0x90 && !REX_B(s)) {
|
|
||||||
if (s->prefix & PREFIX_REPZ) {
|
|
||||||
gen_update_cc_op(s);
|
|
||||||
gen_update_eip_cur(s);
|
|
||||||
gen_helper_pause(tcg_env, cur_insn_len_i32(s));
|
|
||||||
s->base.is_jmp = DISAS_NORETURN;
|
|
||||||
}
|
|
||||||
/* No writeback. */
|
|
||||||
decode->op[0].unit = X86_OP_SKIP;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->prefix & PREFIX_LOCK) {
|
if (s->prefix & PREFIX_LOCK) {
|
||||||
tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1,
|
tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1,
|
||||||
s->mem_index, decode->op[0].ot | MO_LE);
|
s->mem_index, decode->op[0].ot | MO_LE);
|
||||||
|
@ -140,6 +140,26 @@ G_NORETURN void raise_exception_ra(CPUX86State *env, int exception_index,
|
|||||||
raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
|
raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_NORETURN void helper_icebp(CPUX86State *env)
|
||||||
|
{
|
||||||
|
CPUState *cs = env_cpu(env);
|
||||||
|
|
||||||
|
do_end_instruction(env);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* INT1 aka ICEBP generates a trap-like #DB, but it is pretty special.
|
||||||
|
*
|
||||||
|
* "Although the ICEBP instruction dispatches through IDT vector 1,
|
||||||
|
* that event is not interceptable by means of the #DB exception
|
||||||
|
* intercept". Instead there is a separate fault-like ICEBP intercept.
|
||||||
|
*/
|
||||||
|
cs->exception_index = EXCP01_DB;
|
||||||
|
env->error_code = 0;
|
||||||
|
env->exception_is_int = 0;
|
||||||
|
env->exception_next_eip = env->eip;
|
||||||
|
cpu_loop_exit(cs);
|
||||||
|
}
|
||||||
|
|
||||||
G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr,
|
G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr,
|
||||||
MMUAccessType access_type,
|
MMUAccessType access_type,
|
||||||
uintptr_t retaddr)
|
uintptr_t retaddr)
|
||||||
|
@ -91,7 +91,6 @@ extern const uint8_t parity_table[256];
|
|||||||
|
|
||||||
/* misc_helper.c */
|
/* misc_helper.c */
|
||||||
void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask);
|
void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask);
|
||||||
G_NORETURN void do_pause(CPUX86State *env);
|
|
||||||
|
|
||||||
/* sysemu/svm_helper.c */
|
/* sysemu/svm_helper.c */
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
@ -111,7 +110,17 @@ int exception_has_error_code(int intno);
|
|||||||
/* smm_helper.c */
|
/* smm_helper.c */
|
||||||
void do_smm_enter(X86CPU *cpu);
|
void do_smm_enter(X86CPU *cpu);
|
||||||
|
|
||||||
/* bpt_helper.c */
|
/* sysemu/bpt_helper.c */
|
||||||
bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update);
|
bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the tasks usually performed by gen_eob(). Callers of this function
|
||||||
|
* should also handle TF as appropriate.
|
||||||
|
*/
|
||||||
|
static inline void do_end_instruction(CPUX86State *env)
|
||||||
|
{
|
||||||
|
/* needed if sti is just before */
|
||||||
|
env->hflags &= ~HF_INHIBIT_IRQ_MASK;
|
||||||
|
env->eflags &= ~HF_RF_MASK;
|
||||||
|
}
|
||||||
#endif /* I386_HELPER_TCG_H */
|
#endif /* I386_HELPER_TCG_H */
|
||||||
|
@ -88,23 +88,19 @@ G_NORETURN void helper_rdpmc(CPUX86State *env)
|
|||||||
raise_exception_err(env, EXCP06_ILLOP, 0);
|
raise_exception_err(env, EXCP06_ILLOP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_NORETURN void do_pause(CPUX86State *env)
|
G_NORETURN void helper_pause(CPUX86State *env)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
|
|
||||||
|
/* Do gen_eob() tasks before going back to the main loop. */
|
||||||
|
do_end_instruction(env);
|
||||||
|
helper_rechecking_single_step(env);
|
||||||
|
|
||||||
/* Just let another CPU run. */
|
/* Just let another CPU run. */
|
||||||
cs->exception_index = EXCP_INTERRUPT;
|
cs->exception_index = EXCP_INTERRUPT;
|
||||||
cpu_loop_exit(cs);
|
cpu_loop_exit(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_NORETURN void helper_pause(CPUX86State *env, int next_eip_addend)
|
|
||||||
{
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
|
|
||||||
env->eip += next_eip_addend;
|
|
||||||
|
|
||||||
do_pause(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
|
uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
|
||||||
{
|
{
|
||||||
if ((env->cr[4] & CR4_PKE_MASK) == 0) {
|
if ((env->cr[4] & CR4_PKE_MASK) == 0) {
|
||||||
|
@ -526,6 +526,24 @@ static inline unsigned int get_sp_mask(unsigned int e2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int exception_is_fault(int intno)
|
||||||
|
{
|
||||||
|
switch (intno) {
|
||||||
|
/*
|
||||||
|
* #DB can be both fault- and trap-like, but it never sets RF=1
|
||||||
|
* in the RFLAGS value pushed on the stack.
|
||||||
|
*/
|
||||||
|
case EXCP01_DB:
|
||||||
|
case EXCP03_INT3:
|
||||||
|
case EXCP04_INTO:
|
||||||
|
case EXCP08_DBLE:
|
||||||
|
case EXCP12_MCHK:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Everything else including reserved exception is a fault. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int exception_has_error_code(int intno)
|
int exception_has_error_code(int intno)
|
||||||
{
|
{
|
||||||
switch (intno) {
|
switch (intno) {
|
||||||
@ -605,8 +623,9 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||||||
int type, dpl, selector, ss_dpl, cpl;
|
int type, dpl, selector, ss_dpl, cpl;
|
||||||
int has_error_code, new_stack, shift;
|
int has_error_code, new_stack, shift;
|
||||||
uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
|
uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
|
||||||
uint32_t old_eip, sp_mask;
|
uint32_t old_eip, sp_mask, eflags;
|
||||||
int vm86 = env->eflags & VM_MASK;
|
int vm86 = env->eflags & VM_MASK;
|
||||||
|
bool set_rf;
|
||||||
|
|
||||||
has_error_code = 0;
|
has_error_code = 0;
|
||||||
if (!is_int && !is_hw) {
|
if (!is_int && !is_hw) {
|
||||||
@ -614,8 +633,10 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||||||
}
|
}
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
old_eip = next_eip;
|
old_eip = next_eip;
|
||||||
|
set_rf = false;
|
||||||
} else {
|
} else {
|
||||||
old_eip = env->eip;
|
old_eip = env->eip;
|
||||||
|
set_rf = exception_is_fault(intno);
|
||||||
}
|
}
|
||||||
|
|
||||||
dt = &env->idt;
|
dt = &env->idt;
|
||||||
@ -748,6 +769,15 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||||||
}
|
}
|
||||||
push_size <<= shift;
|
push_size <<= shift;
|
||||||
#endif
|
#endif
|
||||||
|
eflags = cpu_compute_eflags(env);
|
||||||
|
/*
|
||||||
|
* AMD states that code breakpoint #DBs clear RF=0, Intel leaves it
|
||||||
|
* as is. AMD behavior could be implemented in check_hw_breakpoints().
|
||||||
|
*/
|
||||||
|
if (set_rf) {
|
||||||
|
eflags |= RF_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
if (shift == 1) {
|
if (shift == 1) {
|
||||||
if (new_stack) {
|
if (new_stack) {
|
||||||
if (vm86) {
|
if (vm86) {
|
||||||
@ -759,7 +789,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||||||
PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
|
PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
|
||||||
PUSHL(ssp, esp, sp_mask, env->regs[R_ESP]);
|
PUSHL(ssp, esp, sp_mask, env->regs[R_ESP]);
|
||||||
}
|
}
|
||||||
PUSHL(ssp, esp, sp_mask, cpu_compute_eflags(env));
|
PUSHL(ssp, esp, sp_mask, eflags);
|
||||||
PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
|
PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
|
||||||
PUSHL(ssp, esp, sp_mask, old_eip);
|
PUSHL(ssp, esp, sp_mask, old_eip);
|
||||||
if (has_error_code) {
|
if (has_error_code) {
|
||||||
@ -776,7 +806,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||||||
PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
|
PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
|
||||||
PUSHW(ssp, esp, sp_mask, env->regs[R_ESP]);
|
PUSHW(ssp, esp, sp_mask, env->regs[R_ESP]);
|
||||||
}
|
}
|
||||||
PUSHW(ssp, esp, sp_mask, cpu_compute_eflags(env));
|
PUSHW(ssp, esp, sp_mask, eflags);
|
||||||
PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
|
PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
|
||||||
PUSHW(ssp, esp, sp_mask, old_eip);
|
PUSHW(ssp, esp, sp_mask, old_eip);
|
||||||
if (has_error_code) {
|
if (has_error_code) {
|
||||||
@ -868,8 +898,9 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
|||||||
target_ulong ptr;
|
target_ulong ptr;
|
||||||
int type, dpl, selector, cpl, ist;
|
int type, dpl, selector, cpl, ist;
|
||||||
int has_error_code, new_stack;
|
int has_error_code, new_stack;
|
||||||
uint32_t e1, e2, e3, ss;
|
uint32_t e1, e2, e3, ss, eflags;
|
||||||
target_ulong old_eip, esp, offset;
|
target_ulong old_eip, esp, offset;
|
||||||
|
bool set_rf;
|
||||||
|
|
||||||
has_error_code = 0;
|
has_error_code = 0;
|
||||||
if (!is_int && !is_hw) {
|
if (!is_int && !is_hw) {
|
||||||
@ -877,8 +908,10 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
|||||||
}
|
}
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
old_eip = next_eip;
|
old_eip = next_eip;
|
||||||
|
set_rf = false;
|
||||||
} else {
|
} else {
|
||||||
old_eip = env->eip;
|
old_eip = env->eip;
|
||||||
|
set_rf = exception_is_fault(intno);
|
||||||
}
|
}
|
||||||
|
|
||||||
dt = &env->idt;
|
dt = &env->idt;
|
||||||
@ -950,9 +983,15 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
|||||||
}
|
}
|
||||||
esp &= ~0xfLL; /* align stack */
|
esp &= ~0xfLL; /* align stack */
|
||||||
|
|
||||||
|
/* See do_interrupt_protected. */
|
||||||
|
eflags = cpu_compute_eflags(env);
|
||||||
|
if (set_rf) {
|
||||||
|
eflags |= RF_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
PUSHQ(esp, env->segs[R_SS].selector);
|
PUSHQ(esp, env->segs[R_SS].selector);
|
||||||
PUSHQ(esp, env->regs[R_ESP]);
|
PUSHQ(esp, env->regs[R_ESP]);
|
||||||
PUSHQ(esp, cpu_compute_eflags(env));
|
PUSHQ(esp, eflags);
|
||||||
PUSHQ(esp, env->segs[R_CS].selector);
|
PUSHQ(esp, env->segs[R_CS].selector);
|
||||||
PUSHQ(esp, old_eip);
|
PUSHQ(esp, old_eip);
|
||||||
if (has_error_code) {
|
if (has_error_code) {
|
||||||
|
@ -215,6 +215,12 @@ void breakpoint_handler(CPUState *cs)
|
|||||||
if (cs->watchpoint_hit->flags & BP_CPU) {
|
if (cs->watchpoint_hit->flags & BP_CPU) {
|
||||||
cs->watchpoint_hit = NULL;
|
cs->watchpoint_hit = NULL;
|
||||||
if (check_hw_breakpoints(env, false)) {
|
if (check_hw_breakpoints(env, false)) {
|
||||||
|
/*
|
||||||
|
* FIXME: #DB should be delayed by one instruction if
|
||||||
|
* INHIBIT_IRQ is set (STI cannot trigger a watchpoint).
|
||||||
|
* The delayed #DB should also fuse with one generated
|
||||||
|
* by ICEBP (aka INT1).
|
||||||
|
*/
|
||||||
raise_exception(env, EXCP01_DB);
|
raise_exception(env, EXCP01_DB);
|
||||||
} else {
|
} else {
|
||||||
cpu_loop_exit_noexc(cs);
|
cpu_loop_exit_noexc(cs);
|
||||||
@ -238,6 +244,12 @@ target_ulong helper_get_dr(CPUX86State *env, int reg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (env->dr[7] & DR7_GD) {
|
||||||
|
env->dr[7] &= ~DR7_GD;
|
||||||
|
env->dr[6] |= DR6_BD;
|
||||||
|
raise_exception_ra(env, EXCP01_DB, GETPC());
|
||||||
|
}
|
||||||
|
|
||||||
return env->dr[reg];
|
return env->dr[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +263,12 @@ void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (env->dr[7] & DR7_GD) {
|
||||||
|
env->dr[7] &= ~DR7_GD;
|
||||||
|
env->dr[6] |= DR6_BD;
|
||||||
|
raise_exception_ra(env, EXCP01_DB, GETPC());
|
||||||
|
}
|
||||||
|
|
||||||
if (reg < 4) {
|
if (reg < 4) {
|
||||||
if (hw_breakpoint_enabled(env->dr[7], reg)
|
if (hw_breakpoint_enabled(env->dr[7], reg)
|
||||||
&& hw_breakpoint_type(env->dr[7], reg) != DR7_TYPE_IO_RW) {
|
&& hw_breakpoint_type(env->dr[7], reg) != DR7_TYPE_IO_RW) {
|
||||||
|
@ -516,25 +516,16 @@ void helper_flush_page(CPUX86State *env, target_ulong addr)
|
|||||||
tlb_flush_page(env_cpu(env), addr);
|
tlb_flush_page(env_cpu(env), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static G_NORETURN
|
G_NORETURN void helper_hlt(CPUX86State *env)
|
||||||
void do_hlt(CPUX86State *env)
|
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
|
|
||||||
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
|
do_end_instruction(env);
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
cs->exception_index = EXCP_HLT;
|
cs->exception_index = EXCP_HLT;
|
||||||
cpu_loop_exit(cs);
|
cpu_loop_exit(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_NORETURN void helper_hlt(CPUX86State *env, int next_eip_addend)
|
|
||||||
{
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
|
|
||||||
env->eip += next_eip_addend;
|
|
||||||
|
|
||||||
do_hlt(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void helper_monitor(CPUX86State *env, target_ulong ptr)
|
void helper_monitor(CPUX86State *env, target_ulong ptr)
|
||||||
{
|
{
|
||||||
if ((uint32_t)env->regs[R_ECX] != 0) {
|
if ((uint32_t)env->regs[R_ECX] != 0) {
|
||||||
@ -556,8 +547,8 @@ G_NORETURN void helper_mwait(CPUX86State *env, int next_eip_addend)
|
|||||||
|
|
||||||
/* XXX: not complete but not completely erroneous */
|
/* XXX: not complete but not completely erroneous */
|
||||||
if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
|
if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
|
||||||
do_pause(env);
|
helper_pause(env);
|
||||||
} else {
|
} else {
|
||||||
do_hlt(env);
|
helper_hlt(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,15 +130,26 @@ void x86_cpu_do_interrupt(CPUState *cs)
|
|||||||
|
|
||||||
bool x86_cpu_exec_halt(CPUState *cpu)
|
bool x86_cpu_exec_halt(CPUState *cpu)
|
||||||
{
|
{
|
||||||
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
CPUX86State *env = &x86_cpu->env;
|
||||||
|
|
||||||
|
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
||||||
bql_lock();
|
bql_lock();
|
||||||
apic_poll_irq(x86_cpu->apic_state);
|
apic_poll_irq(x86_cpu->apic_state);
|
||||||
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
||||||
bql_unlock();
|
bql_unlock();
|
||||||
}
|
}
|
||||||
return cpu_has_work(cpu);
|
|
||||||
|
if (!cpu_has_work(cpu)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete HLT instruction. */
|
||||||
|
if (env->eflags & TF_MASK) {
|
||||||
|
env->dr[6] |= DR6_BS;
|
||||||
|
do_interrupt_all(x86_cpu, EXCP01_DB, 0, 0, env->eip, 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool x86_need_replay_interrupt(int interrupt_request)
|
bool x86_need_replay_interrupt(int interrupt_request)
|
||||||
|
@ -163,6 +163,8 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
uint64_t new_cr0;
|
uint64_t new_cr0;
|
||||||
uint64_t new_cr3;
|
uint64_t new_cr3;
|
||||||
uint64_t new_cr4;
|
uint64_t new_cr4;
|
||||||
|
uint64_t new_dr6;
|
||||||
|
uint64_t new_dr7;
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
@ -252,6 +254,13 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
control.intercept_exceptions
|
control.intercept_exceptions
|
||||||
));
|
));
|
||||||
|
|
||||||
|
env->hflags &= ~HF_INHIBIT_IRQ_MASK;
|
||||||
|
if (x86_ldl_phys(cs, env->vm_vmcb +
|
||||||
|
offsetof(struct vmcb, control.int_state)) &
|
||||||
|
SVM_INTERRUPT_SHADOW_MASK) {
|
||||||
|
env->hflags |= HF_INHIBIT_IRQ_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||||
control.nested_ctl));
|
control.nested_ctl));
|
||||||
asid = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
asid = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
|
||||||
@ -361,20 +370,22 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
env->vm_vmcb + offsetof(struct vmcb, save.rsp));
|
env->vm_vmcb + offsetof(struct vmcb, save.rsp));
|
||||||
env->regs[R_EAX] = x86_ldq_phys(cs,
|
env->regs[R_EAX] = x86_ldq_phys(cs,
|
||||||
env->vm_vmcb + offsetof(struct vmcb, save.rax));
|
env->vm_vmcb + offsetof(struct vmcb, save.rax));
|
||||||
env->dr[7] = x86_ldq_phys(cs,
|
|
||||||
env->vm_vmcb + offsetof(struct vmcb, save.dr7));
|
new_dr7 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.dr7));
|
||||||
env->dr[6] = x86_ldq_phys(cs,
|
new_dr6 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.dr6));
|
||||||
env->vm_vmcb + offsetof(struct vmcb, save.dr6));
|
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
if (env->dr[6] & DR_RESERVED_MASK) {
|
if (new_dr7 & DR_RESERVED_MASK) {
|
||||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||||
}
|
}
|
||||||
if (env->dr[7] & DR_RESERVED_MASK) {
|
if (new_dr6 & DR_RESERVED_MASK) {
|
||||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cpu_x86_update_dr7(env, new_dr7);
|
||||||
|
env->dr[6] = new_dr6;
|
||||||
|
|
||||||
if (is_efer_invalid_state(env)) {
|
if (is_efer_invalid_state(env)) {
|
||||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||||
}
|
}
|
||||||
@ -811,8 +822,12 @@ void do_vmexit(CPUX86State *env)
|
|||||||
env->hflags &= ~HF_GUEST_MASK;
|
env->hflags &= ~HF_GUEST_MASK;
|
||||||
env->intercept = 0;
|
env->intercept = 0;
|
||||||
env->intercept_exceptions = 0;
|
env->intercept_exceptions = 0;
|
||||||
|
|
||||||
|
/* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
|
||||||
cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
|
cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
|
||||||
env->int_ctl = 0;
|
env->int_ctl = 0;
|
||||||
|
|
||||||
|
/* Clears the TSC_OFFSET inside the processor. */
|
||||||
env->tsc_offset = 0;
|
env->tsc_offset = 0;
|
||||||
|
|
||||||
env->gdt.base = x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
|
env->gdt.base = x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
|
||||||
@ -832,6 +847,15 @@ void do_vmexit(CPUX86State *env)
|
|||||||
cpu_x86_update_cr4(env, x86_ldq_phys(cs,
|
cpu_x86_update_cr4(env, x86_ldq_phys(cs,
|
||||||
env->vm_hsave + offsetof(struct vmcb,
|
env->vm_hsave + offsetof(struct vmcb,
|
||||||
save.cr4)));
|
save.cr4)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resets the current ASID register to zero (host ASID; TLB flush).
|
||||||
|
*
|
||||||
|
* If the host is in PAE mode, the processor reloads the host's PDPEs
|
||||||
|
* from the page table indicated the host's CR3. FIXME: If the PDPEs
|
||||||
|
* contain illegal state, the processor causes a shutdown (QEMU does
|
||||||
|
* not implement PDPTRs).
|
||||||
|
*/
|
||||||
cpu_x86_update_cr3(env, x86_ldq_phys(cs,
|
cpu_x86_update_cr3(env, x86_ldq_phys(cs,
|
||||||
env->vm_hsave + offsetof(struct vmcb,
|
env->vm_hsave + offsetof(struct vmcb,
|
||||||
save.cr3)));
|
save.cr3)));
|
||||||
@ -839,12 +863,14 @@ void do_vmexit(CPUX86State *env)
|
|||||||
set properly */
|
set properly */
|
||||||
cpu_load_efer(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
|
cpu_load_efer(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
|
||||||
save.efer)));
|
save.efer)));
|
||||||
|
|
||||||
|
/* Completion of the VMRUN instruction clears the host EFLAGS.RF bit. */
|
||||||
env->eflags = 0;
|
env->eflags = 0;
|
||||||
cpu_load_eflags(env, x86_ldq_phys(cs,
|
cpu_load_eflags(env, x86_ldq_phys(cs,
|
||||||
env->vm_hsave + offsetof(struct vmcb,
|
env->vm_hsave + offsetof(struct vmcb,
|
||||||
save.rflags)),
|
save.rflags)),
|
||||||
~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK |
|
~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK |
|
||||||
VM_MASK));
|
RF_MASK | VM_MASK));
|
||||||
|
|
||||||
svm_load_seg_cache(env, MMU_PHYS_IDX,
|
svm_load_seg_cache(env, MMU_PHYS_IDX,
|
||||||
env->vm_hsave + offsetof(struct vmcb, save.es), R_ES);
|
env->vm_hsave + offsetof(struct vmcb, save.es), R_ES);
|
||||||
@ -864,8 +890,11 @@ void do_vmexit(CPUX86State *env)
|
|||||||
|
|
||||||
env->dr[6] = x86_ldq_phys(cs,
|
env->dr[6] = x86_ldq_phys(cs,
|
||||||
env->vm_hsave + offsetof(struct vmcb, save.dr6));
|
env->vm_hsave + offsetof(struct vmcb, save.dr6));
|
||||||
env->dr[7] = x86_ldq_phys(cs,
|
|
||||||
env->vm_hsave + offsetof(struct vmcb, save.dr7));
|
/* Disables all breakpoints in the host DR7 register. */
|
||||||
|
cpu_x86_update_dr7(env,
|
||||||
|
x86_ldq_phys(cs,
|
||||||
|
env->vm_hsave + offsetof(struct vmcb, save.dr7)) & ~0xff);
|
||||||
|
|
||||||
/* other setups */
|
/* other setups */
|
||||||
x86_stl_phys(cs,
|
x86_stl_phys(cs,
|
||||||
@ -881,21 +910,17 @@ void do_vmexit(CPUX86State *env)
|
|||||||
|
|
||||||
env->hflags2 &= ~HF2_GIF_MASK;
|
env->hflags2 &= ~HF2_GIF_MASK;
|
||||||
env->hflags2 &= ~HF2_VGIF_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. */
|
|
||||||
|
|
||||||
/* Clears the TSC_OFFSET inside the processor. */
|
/* FIXME: Checks the reloaded host state for consistency. */
|
||||||
|
|
||||||
/* If the host is in PAE mode, the processor reloads the host's PDPEs
|
/*
|
||||||
from the page table indicated the host's CR3. If the PDPEs contain
|
* EFLAGS.TF causes a #DB trap after the VMRUN completes on the host
|
||||||
illegal state, the processor causes a shutdown. */
|
* side (i.e., after the #VMEXIT from the guest). Since we're running
|
||||||
|
* in the main loop, call do_interrupt_all directly.
|
||||||
/* Disables all breakpoints in the host DR7 register. */
|
*/
|
||||||
|
if ((env->eflags & TF_MASK) != 0) {
|
||||||
/* Checks the reloaded host state for consistency. */
|
env->dr[6] |= DR6_BS;
|
||||||
|
do_interrupt_all(X86_CPU(cs), EXCP01_DB, 0, 0, env->eip, 0);
|
||||||
/* If the host's rIP reloaded by #VMEXIT is outside the limit of the
|
}
|
||||||
host's code segment or non-canonical (in the case of long mode), a
|
|
||||||
#GP fault is delivered inside the host. */
|
|
||||||
}
|
}
|
||||||
|
@ -549,6 +549,19 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_update_eip_next(DisasContext *s)
|
||||||
|
{
|
||||||
|
assert(s->pc_save != -1);
|
||||||
|
if (tb_cflags(s->base.tb) & CF_PCREL) {
|
||||||
|
tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
|
||||||
|
} else if (CODE64(s)) {
|
||||||
|
tcg_gen_movi_tl(cpu_eip, s->pc);
|
||||||
|
} else {
|
||||||
|
tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->pc - s->cs_base));
|
||||||
|
}
|
||||||
|
s->pc_save = s->pc;
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_update_eip_cur(DisasContext *s)
|
static void gen_update_eip_cur(DisasContext *s)
|
||||||
{
|
{
|
||||||
assert(s->pc_save != -1);
|
assert(s->pc_save != -1);
|
||||||
@ -2125,7 +2138,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the FrameTemp value to EBP. */
|
/* Copy the FrameTemp value to EBP. */
|
||||||
gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
|
gen_op_mov_reg_v(s, d_ot, R_EBP, s->T1);
|
||||||
|
|
||||||
/* Compute the final value of ESP. */
|
/* Compute the final value of ESP. */
|
||||||
tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
|
tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
|
||||||
@ -3732,6 +3745,11 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
}
|
}
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
gen_update_eip_cur(s);
|
gen_update_eip_cur(s);
|
||||||
|
/*
|
||||||
|
* Reloads INHIBIT_IRQ mask as well as TF and RF with guest state.
|
||||||
|
* The usual gen_eob() handling is performed on vmexit after
|
||||||
|
* host state is reloaded.
|
||||||
|
*/
|
||||||
gen_helper_vmrun(tcg_env, tcg_constant_i32(s->aflag - 1),
|
gen_helper_vmrun(tcg_env, tcg_constant_i32(s->aflag - 1),
|
||||||
cur_insn_len_i32(s));
|
cur_insn_len_i32(s));
|
||||||
tcg_gen_exit_tb(NULL, 0);
|
tcg_gen_exit_tb(NULL, 0);
|
||||||
@ -4630,6 +4648,14 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
|||||||
* If jmp_opt, we want to handle each string instruction individually.
|
* If jmp_opt, we want to handle each string instruction individually.
|
||||||
* For icount also disable repz optimization so that each iteration
|
* For icount also disable repz optimization so that each iteration
|
||||||
* is accounted separately.
|
* is accounted separately.
|
||||||
|
*
|
||||||
|
* FIXME: this is messy; it makes REP string instructions a lot less
|
||||||
|
* efficient than they should be and it gets in the way of correct
|
||||||
|
* handling of RF (interrupts or traps arriving after any iteration
|
||||||
|
* of a repeated string instruction but the last should set RF to 1).
|
||||||
|
* Perhaps it would be more efficient if REP string instructions were
|
||||||
|
* always at the beginning of the TB, or even their own TB? That
|
||||||
|
* would even allow accounting up to 64k iterations at once for icount.
|
||||||
*/
|
*/
|
||||||
dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT);
|
dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT);
|
||||||
|
|
||||||
@ -4735,6 +4761,17 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
|||||||
|
|
||||||
switch (dc->base.is_jmp) {
|
switch (dc->base.is_jmp) {
|
||||||
case DISAS_NORETURN:
|
case DISAS_NORETURN:
|
||||||
|
/*
|
||||||
|
* Most instructions should not use DISAS_NORETURN, as that suppresses
|
||||||
|
* the handling of hflags normally done by gen_eob(). We can
|
||||||
|
* get here:
|
||||||
|
* - for exception and interrupts
|
||||||
|
* - for jump optimization (which is disabled by INHIBIT_IRQ/RF/TF)
|
||||||
|
* - for VMRUN because RF/TF handling for the host is done after vmexit,
|
||||||
|
* and INHIBIT_IRQ is loaded from the VMCB
|
||||||
|
* - for HLT/PAUSE/MWAIT to exit the main loop with specific EXCP_* values;
|
||||||
|
* the helpers handle themselves the tasks normally done by gen_eob().
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
case DISAS_TOO_MANY:
|
case DISAS_TOO_MANY:
|
||||||
gen_update_cc_op(dc);
|
gen_update_cc_op(dc);
|
||||||
|
@ -57,9 +57,14 @@ int qemu_madvise(void *addr, size_t len, int advice)
|
|||||||
#if defined(CONFIG_MADVISE)
|
#if defined(CONFIG_MADVISE)
|
||||||
return madvise(addr, len, advice);
|
return madvise(addr, len, advice);
|
||||||
#elif defined(CONFIG_POSIX_MADVISE)
|
#elif defined(CONFIG_POSIX_MADVISE)
|
||||||
return posix_madvise(addr, len, advice);
|
int rc = posix_madvise(addr, len, advice);
|
||||||
|
if (rc) {
|
||||||
|
errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
#else
|
#else
|
||||||
errno = EINVAL;
|
errno = ENOSYS;
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user