* kvm: reuse per-vcpu stats fd to avoid vcpu interruption

* Validate cluster and NUMA node boundary on ARM and RISC-V
 * various small TCG features from newer processors
 * Remove dubious 'event_notifier-posix.c' include
 * fix git-submodule.sh in releases
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmSZS0IUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroN+tgf/axJdG9NXKCyXgc0vzjKVhSR4Y+tC
 EPxkg7Rq7uOMgbph9oTS/2Kzh9LnP6kLt2qnS4igRHGuEBd58yD6fFNDv0LJsK/l
 B/d0WGHMKV0KMYOX24rkyfohVu37GhVRsiVSIlIiQVTC9JtYer7WxdnyoDaPKvY8
 dpbKgDrd59vAlsHrpj7ZubVQPcL3lXrLryimpDohMH6Ba+4wZq+7dKPpal97QOP2
 3i7isUBTQiMOcVjW6GEiNcDLSJqj5DSgylhdFnaBsq/ThpC2PxWoXcCbV28QELzf
 5+J+RXQavmeWKZMR0q98iBzWbrsVtaSxAkHHiwbUMMqQvkfY6Dpo5dMHWw==
 =WHE2
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* kvm: reuse per-vcpu stats fd to avoid vcpu interruption
* Validate cluster and NUMA node boundary on ARM and RISC-V
* various small TCG features from newer processors
* Remove dubious 'event_notifier-posix.c' include
* fix git-submodule.sh in releases

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmSZS0IUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroN+tgf/axJdG9NXKCyXgc0vzjKVhSR4Y+tC
# EPxkg7Rq7uOMgbph9oTS/2Kzh9LnP6kLt2qnS4igRHGuEBd58yD6fFNDv0LJsK/l
# B/d0WGHMKV0KMYOX24rkyfohVu37GhVRsiVSIlIiQVTC9JtYer7WxdnyoDaPKvY8
# dpbKgDrd59vAlsHrpj7ZubVQPcL3lXrLryimpDohMH6Ba+4wZq+7dKPpal97QOP2
# 3i7isUBTQiMOcVjW6GEiNcDLSJqj5DSgylhdFnaBsq/ThpC2PxWoXcCbV28QELzf
# 5+J+RXQavmeWKZMR0q98iBzWbrsVtaSxAkHHiwbUMMqQvkfY6Dpo5dMHWw==
# =WHE2
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 26 Jun 2023 10:24:34 AM CEST
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [undefined]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  git-submodule.sh: allow running in validate mode without previous update
  target/i386: implement SYSCALL/SYSRET in 32-bit emulators
  target/i386: implement RDPID in TCG
  target/i386: sysret and sysexit are privileged
  target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode
  target/i386: Intel only supports SYSCALL/SYSRET in long mode
  target/i386: TCG supports WBNOINVD
  target/i386: TCG supports XSAVEERPTR
  target/i386: do not accept RDSEED if CPUID bit absent
  target/i386: TCG supports RDSEED
  target/i386: TCG supports 3DNow! prefetch(w)
  target/i386: fix INVD vmexit
  kvm: reuse per-vcpu stats fd to avoid vcpu interruption
  hw/riscv: Validate cluster and NUMA node boundary
  hw/arm: Validate cluster and NUMA node boundary
  numa: Validate cluster and NUMA node boundary if required
  hw/remote/proxy: Remove dubious 'event_notifier-posix.c' include
  build: further refine build.ninja rules

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-06-26 13:44:16 +02:00
commit cd041ddbc0
22 changed files with 224 additions and 94 deletions

View File

@ -83,16 +83,17 @@ config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh
@if test -f meson-private/coredata.dat; then \
./config.status --skip-meson; \
else \
./config.status && touch build.ninja.stamp; \
./config.status; \
fi
# 2. meson.stamp exists if meson has run at least once (so ninja reconfigure
# works), but otherwise never needs to be updated
meson-private/coredata.dat: meson.stamp
meson.stamp: config-host.mak
@touch meson.stamp
# 3. ensure generated build files are up-to-date
# 3. ensure meson-generated build files are up-to-date
ifneq ($(NINJA),)
Makefile.ninja: build.ninja
@ -106,11 +107,19 @@ Makefile.ninja: build.ninja
endif
ifneq ($(MESON),)
# A separate rule is needed for Makefile dependencies to avoid -n
# The path to meson always points to pyvenv/bin/meson, but the absolute
# paths could change. In that case, force a regeneration of build.ninja.
# Note that this invocation of $(NINJA), just like when Make rebuilds
# Makefiles, does not include -n.
build.ninja: build.ninja.stamp
$(build-files):
build.ninja.stamp: meson.stamp $(build-files)
$(MESON) setup --reconfigure $(SRC_PATH) && touch $@
@if test "$$(cat build.ninja.stamp)" = "$(MESON)" && test -n "$(NINJA)"; then \
$(NINJA) build.ninja; \
else \
echo "$(MESON) setup --reconfigure $(SRC_PATH)"; \
$(MESON) setup --reconfigure $(SRC_PATH); \
fi && echo "$(MESON)" > $@
Makefile.mtest: build.ninja scripts/mtest2make.py
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@

View File

@ -450,6 +450,8 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
"kvm_init_vcpu: kvm_arch_init_vcpu failed (%lu)",
kvm_arch_vcpu_id(cpu));
}
cpu->kvm_vcpu_stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
err:
return ret;
}
@ -4007,7 +4009,7 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
/* Read stats header */
kvm_stats_header = &descriptors->kvm_stats_header;
ret = read(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header));
ret = pread(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header), 0);
if (ret != sizeof(*kvm_stats_header)) {
error_setg(errp, "KVM stats: failed to read stats header: "
"expected %zu actual %zu",
@ -4038,7 +4040,8 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
}
static void query_stats(StatsResultList **result, StatsTarget target,
strList *names, int stats_fd, Error **errp)
strList *names, int stats_fd, CPUState *cpu,
Error **errp)
{
struct kvm_stats_desc *kvm_stats_desc;
struct kvm_stats_header *kvm_stats_header;
@ -4096,7 +4099,7 @@ static void query_stats(StatsResultList **result, StatsTarget target,
break;
case STATS_TARGET_VCPU:
add_stats_entry(result, STATS_PROVIDER_KVM,
current_cpu->parent_obj.canonical_path,
cpu->parent_obj.canonical_path,
stats_list);
break;
default:
@ -4133,10 +4136,9 @@ static void query_stats_schema(StatsSchemaList **result, StatsTarget target,
add_stats_schema(result, STATS_PROVIDER_KVM, target, stats_list);
}
static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
static void query_stats_vcpu(CPUState *cpu, StatsArgs *kvm_stats_args)
{
StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
int stats_fd = cpu->kvm_vcpu_stats_fd;
Error *local_err = NULL;
if (stats_fd == -1) {
@ -4145,14 +4147,13 @@ static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
return;
}
query_stats(kvm_stats_args->result.stats, STATS_TARGET_VCPU,
kvm_stats_args->names, stats_fd, kvm_stats_args->errp);
close(stats_fd);
kvm_stats_args->names, stats_fd, cpu,
kvm_stats_args->errp);
}
static void query_stats_schema_vcpu(CPUState *cpu, run_on_cpu_data data)
static void query_stats_schema_vcpu(CPUState *cpu, StatsArgs *kvm_stats_args)
{
StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
int stats_fd = cpu->kvm_vcpu_stats_fd;
Error *local_err = NULL;
if (stats_fd == -1) {
@ -4162,7 +4163,6 @@ static void query_stats_schema_vcpu(CPUState *cpu, run_on_cpu_data data)
}
query_stats_schema(kvm_stats_args->result.schema, STATS_TARGET_VCPU, stats_fd,
kvm_stats_args->errp);
close(stats_fd);
}
static void query_stats_cb(StatsResultList **result, StatsTarget target,
@ -4180,7 +4180,7 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target,
error_setg_errno(errp, errno, "KVM stats: ioctl failed");
return;
}
query_stats(result, target, names, stats_fd, errp);
query_stats(result, target, names, stats_fd, NULL, errp);
close(stats_fd);
break;
}
@ -4194,7 +4194,7 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target,
if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
continue;
}
run_on_cpu(cpu, query_stats_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
query_stats_vcpu(cpu, &stats_args);
}
break;
}
@ -4220,6 +4220,6 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
if (first_cpu) {
stats_args.result.schema = result;
stats_args.errp = errp;
run_on_cpu(first_cpu, query_stats_schema_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
query_stats_schema_vcpu(first_cpu, &stats_args);
}
}

View File

@ -164,6 +164,10 @@ static inline void target_cpu_loop(CPUX86State *env)
}
break;
case EXCP_SYSCALL:
/* doesn't do anything */
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;

3
configure vendored
View File

@ -758,7 +758,7 @@ done
if ! test -e "$source_path/.git"
then
git_submodules_action="ignore"
git_submodules_action="validate"
fi
# test for any invalid configuration combinations
@ -1895,6 +1895,7 @@ if test "$skip_meson" = no; then
if test "$?" -ne 0 ; then
error_exit "meson setup failed"
fi
echo "$meson" > build.ninja.stamp
else
if test -f meson-private/cmd_line.txt; then
# Adjust old command line options that were removed

View File

@ -910,6 +910,8 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data)
mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;
mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id;
/* platform instead of architectural choice */
mc->cpu_cluster_has_numa_boundary = true;
}
static const TypeInfo sbsa_ref_info = {

View File

@ -3033,6 +3033,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
mc->smp_props.clusters_supported = true;
mc->auto_enable_numa_with_memhp = true;
mc->auto_enable_numa_with_memdev = true;
/* platform instead of architectural choice */
mc->cpu_cluster_has_numa_boundary = true;
mc->default_ram_id = "mach-virt.ram";
mc->default_nic = "virtio-net-pci";

View File

@ -1262,6 +1262,45 @@ static void machine_numa_finish_cpu_init(MachineState *machine)
g_string_free(s, true);
}
static void validate_cpu_cluster_to_numa_boundary(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
NumaState *state = ms->numa_state;
const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
const CPUArchId *cpus = possible_cpus->cpus;
int i, j;
if (state->num_nodes <= 1 || possible_cpus->len <= 1) {
return;
}
/*
* The Linux scheduling domain can't be parsed when the multiple CPUs
* in one cluster have been associated with different NUMA nodes. However,
* it's fine to associate one NUMA node with CPUs in different clusters.
*/
for (i = 0; i < possible_cpus->len; i++) {
for (j = i + 1; j < possible_cpus->len; j++) {
if (cpus[i].props.has_socket_id &&
cpus[i].props.has_cluster_id &&
cpus[i].props.has_node_id &&
cpus[j].props.has_socket_id &&
cpus[j].props.has_cluster_id &&
cpus[j].props.has_node_id &&
cpus[i].props.socket_id == cpus[j].props.socket_id &&
cpus[i].props.cluster_id == cpus[j].props.cluster_id &&
cpus[i].props.node_id != cpus[j].props.node_id) {
warn_report("CPU-%d and CPU-%d in socket-%" PRId64 "-cluster-%" PRId64
" have been associated with node-%" PRId64 " and node-%" PRId64
" respectively. It can cause OSes like Linux to"
" misbehave", i, j, cpus[i].props.socket_id,
cpus[i].props.cluster_id, cpus[i].props.node_id,
cpus[j].props.node_id);
}
}
}
}
MemoryRegion *machine_consume_memdev(MachineState *machine,
HostMemoryBackend *backend)
{
@ -1355,6 +1394,9 @@ void machine_run_board_init(MachineState *machine, const char *mem_path, Error *
numa_complete_configuration(machine);
if (machine->numa_state->num_nodes) {
machine_numa_finish_cpu_init(machine);
if (machine_class->cpu_cluster_has_numa_boundary) {
validate_cpu_cluster_to_numa_boundary(machine);
}
}
}

View File

@ -22,7 +22,6 @@
#include "qom/object.h"
#include "qemu/event_notifier.h"
#include "sysemu/kvm.h"
#include "util/event_notifier-posix.c"
static void probe_pci_info(PCIDevice *dev, Error **errp);
static void proxy_device_reset(DeviceState *dev);

View File

@ -354,6 +354,8 @@ static void spike_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
mc->numa_mem_supported = true;
/* platform instead of architectural choice */
mc->cpu_cluster_has_numa_boundary = true;
mc->default_ram_id = "riscv.spike.ram";
object_class_property_add_str(oc, "signature", NULL, spike_set_signature);
object_class_property_set_description(oc, "signature",

View File

@ -1669,6 +1669,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
mc->numa_mem_supported = true;
/* platform instead of architectural choice */
mc->cpu_cluster_has_numa_boundary = true;
mc->default_ram_id = "riscv_virt_board.ram";
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;

View File

@ -274,6 +274,7 @@ struct MachineClass {
bool nvdimm_supported;
bool numa_mem_supported;
bool auto_enable_numa;
bool cpu_cluster_has_numa_boundary;
SMPCompatProps smp_props;
const char *default_ram_id;

View File

@ -402,6 +402,7 @@ struct CPUState {
struct kvm_dirty_gfn *kvm_dirty_gfns;
uint32_t kvm_fetch_index;
uint64_t dirty_pages;
int kvm_vcpu_stats_fd;
/* Use by accel-block: CPU is executing an ioctl() */
QemuLockCnt in_ioctl_lock;

View File

@ -211,6 +211,9 @@ void cpu_loop(CPUX86State *env)
switch(trapnr) {
case 0x80:
#ifndef TARGET_X86_64
case EXCP_SYSCALL:
#endif
/* linux syscall from int $0x80 */
ret = do_syscall(env,
env->regs[R_EAX],
@ -227,9 +230,9 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EAX] = ret;
}
break;
#ifndef TARGET_ABI32
#ifdef TARGET_X86_64
case EXCP_SYSCALL:
/* linux syscall from syscall instruction */
/* linux syscall from syscall instruction. */
ret = do_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
@ -245,8 +248,6 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EAX] = ret;
}
break;
#endif
#ifdef TARGET_X86_64
case EXCP_VSYSCALL:
emulate_vsyscall(env);
break;

View File

@ -2232,6 +2232,8 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
# Note that we need to specify prefix: here to avoid incorrectly
# thinking that Windows has posix_memalign()
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))

View File

@ -9,13 +9,22 @@ command=$1
shift
maybe_modules="$@"
# if not running in a git checkout, do nothing
test "$command" = "ignore" && exit 0
test -z "$maybe_modules" && exit 0
test -z "$GIT" && GIT=$(command -v git)
cd "$(dirname "$0")/.."
no_git_error=
if ! test -e ".git"; then
no_git_error='no git checkout exists'
elif test -z "$GIT"; then
no_git_error='git binary not found'
fi
is_git() {
test -z "$no_git_error"
}
update_error() {
echo "$0: $*"
echo
@ -34,7 +43,7 @@ update_error() {
}
validate_error() {
if test "$1" = "validate"; then
if is_git && test "$1" = "validate"; then
echo "GIT submodules checkout is out of date, and submodules"
echo "configured for validate only. Please run"
echo " scripts/git-submodule.sh update $maybe_modules"
@ -51,42 +60,42 @@ check_updated() {
test "$CURSTATUS" = "$OLDSTATUS"
}
if test -n "$maybe_modules" && ! test -e ".git"
then
echo "$0: unexpectedly called with submodules but no git checkout exists"
exit 1
if is_git; then
test -e $substat || touch $substat
modules=""
for m in $maybe_modules
do
$GIT submodule status $m 1> /dev/null 2>&1
if test $? = 0
then
modules="$modules $m"
grep $m $substat > /dev/null 2>&1 || $GIT submodule status $module >> $substat
else
echo "warn: ignoring non-existent submodule $m"
fi
done
else
modules=$maybe_modules
fi
if test -n "$maybe_modules" && test -z "$GIT"
then
echo "$0: unexpectedly called with submodules but git binary not found"
exit 1
fi
modules=""
for m in $maybe_modules
do
$GIT submodule status $m 1> /dev/null 2>&1
if test $? = 0
then
modules="$modules $m"
else
echo "warn: ignoring non-existent submodule $m"
fi
done
case "$command" in
status|validate)
test -f "$substat" || validate_error "$command"
test -z "$maybe_modules" && exit 0
for module in $modules; do
check_updated $module || validate_error "$command"
if is_git; then
check_updated $module || validate_error "$command"
elif ! (set xyz "$module"/* && test -e "$2"); then
# The directory does not exist or it contains no files
echo "$0: sources not available for $module and $no_git_error"
validate_error "$command"
fi
done
exit 0
;;
update)
test -e $substat || touch $substat
test -z "$maybe_modules" && exit 0
is_git || {
echo "$0: unexpectedly called with submodules but $no_git_error"
exit 1
}
$GIT submodule update --init $modules 1>/dev/null
test $? -ne 0 && update_error "failed to update modules"

View File

@ -637,7 +637,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER */
#ifdef TARGET_X86_64
#define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM)
#define TCG_EXT2_X86_64_FEATURES CPUID_EXT2_LM
#else
#define TCG_EXT2_X86_64_FEATURES 0
#endif
@ -645,9 +645,10 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
TCG_EXT2_X86_64_FEATURES)
CPUID_EXT2_SYSCALL | TCG_EXT2_X86_64_FEATURES)
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | \
CPUID_EXT3_3DNOWPREFETCH)
#define TCG_EXT4_FEATURES 0
#define TCG_SVM_FEATURES (CPUID_SVM_NPT | CPUID_SVM_VGIF | \
CPUID_SVM_SVME_ADDR_CHK)
@ -656,14 +657,21 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2)
CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED)
/* missing:
CPUID_7_0_EBX_HLE
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
CPUID_7_0_EBX_RDSEED */
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
#if defined CONFIG_SOFTMMU || defined CONFIG_LINUX
#define TCG_7_0_ECX_RDPID CPUID_7_0_ECX_RDPID
#else
#define TCG_7_0_ECX_RDPID 0
#endif
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES)
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES | \
TCG_7_0_ECX_RDPID)
#define TCG_7_0_EDX_FEATURES CPUID_7_0_EDX_FSRM
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
CPUID_7_1_EAX_FSRC)
@ -678,6 +686,9 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_SGX_12_0_EBX_FEATURES 0
#define TCG_SGX_12_1_EAX_FEATURES 0
#define TCG_8000_0008_EBX (CPUID_8000_0008_EBX_XSAVEERPTR | \
CPUID_8000_0008_EBX_WBNOINVD)
FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
[FEAT_1_EDX] = {
.type = CPUID_FEATURE_WORD,
@ -939,7 +950,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"amd-psfd", NULL, NULL, NULL,
},
.cpuid = { .eax = 0x80000008, .reg = R_EBX, },
.tcg_features = 0,
.tcg_features = TCG_8000_0008_EBX,
.unmigratable_flags = 0,
},
[FEAT_8000_0021_EAX] = {
@ -6235,6 +6246,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ecx |= 1 << 1; /* CmpLegacy bit */
}
}
if (tcg_enabled() && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 &&
!(env->hflags & HF_LMA_MASK)) {
*edx &= ~CPUID_EXT2_SYSCALL;
}
break;
case 0x80000002:
case 0x80000003:

View File

@ -51,10 +51,8 @@ DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
DEF_HELPER_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int)
#ifdef TARGET_X86_64
DEF_HELPER_2(syscall, void, env, int)
DEF_HELPER_2(sysret, void, env, int)
#endif
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, 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)
@ -69,8 +67,8 @@ DEF_HELPER_2(into, void, env, int)
DEF_HELPER_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_1(rechecking_single_step, void, env)
DEF_HELPER_1(cpuid, void, env)
DEF_HELPER_FLAGS_1(rdpid, TCG_CALL_NO_WG, tl, env)
DEF_HELPER_1(rdtsc, void, env)
DEF_HELPER_1(rdtscp, void, env)
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
#ifndef CONFIG_USER_ONLY

View File

@ -75,12 +75,6 @@ void helper_rdtsc(CPUX86State *env)
env->regs[R_EDX] = (uint32_t)(val >> 32);
}
void helper_rdtscp(CPUX86State *env)
{
helper_rdtsc(env);
env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
}
G_NORETURN void helper_rdpmc(CPUX86State *env)
{
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
@ -137,3 +131,18 @@ void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
env->pkru = val;
tlb_flush(cs);
}
target_ulong HELPER(rdpid)(CPUX86State *env)
{
#if defined CONFIG_SOFTMMU
return env->tsc_aux;
#elif defined CONFIG_LINUX && defined CONFIG_GETCPU
unsigned cpu, node;
getcpu(&cpu, &node);
return (node << 12) | (cpu & 0xfff);
#elif defined CONFIG_SCHED_GETCPU
return sched_getcpu();
#else
return 0;
#endif
}

View File

@ -977,6 +977,7 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
e2);
env->eip = offset;
}
#endif /* TARGET_X86_64 */
void helper_sysret(CPUX86State *env, int dflag)
{
@ -990,6 +991,7 @@ void helper_sysret(CPUX86State *env, int dflag)
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
}
selector = (env->star >> 48) & 0xffff;
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
| ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
@ -1015,7 +1017,9 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK);
} else {
} else
#endif
{
env->eflags |= IF_MASK;
cpu_x86_load_seg_cache(env, R_CS, selector | 3,
0, 0xffffffff,
@ -1030,7 +1034,6 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_W_MASK | DESC_A_MASK);
}
}
#endif /* TARGET_X86_64 */
/* real mode interrupt */
static void do_interrupt_real(CPUX86State *env, int intno, int is_int,

View File

@ -26,7 +26,6 @@
#include "tcg/helper-tcg.h"
#include "../seg_helper.h"
#ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend)
{
int selector;
@ -35,6 +34,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
}
selector = (env->star >> 32) & 0xffff;
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
int code64;
@ -61,7 +61,9 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
} else {
env->eip = env->cstar;
}
} else {
} else
#endif
{
env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
@ -78,7 +80,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
env->eip = (uint32_t)env->star;
}
}
#endif /* TARGET_X86_64 */
void handle_even_inj(CPUX86State *env, int intno, int is_int,
int error_code, int is_hw, int rm)

View File

@ -3924,13 +3924,33 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_cmpxchg8b(s, env, modrm);
break;
case 7: /* RDSEED */
case 7: /* RDSEED, RDPID with f3 prefix */
if (mod != 3 ||
(s->prefix & (PREFIX_LOCK | PREFIX_REPNZ))) {
goto illegal_op;
}
if (s->prefix & PREFIX_REPZ) {
if (!(s->cpuid_ext_features & CPUID_7_0_ECX_RDPID)) {
goto illegal_op;
}
gen_helper_rdpid(s->T0, cpu_env);
rm = (modrm & 7) | REX_B(s);
gen_op_mov_reg_v(s, dflag, rm, s->T0);
break;
} else {
if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
goto illegal_op;
}
goto do_rdrand;
}
case 6: /* RDRAND */
if (mod != 3 ||
(s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
!(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
goto illegal_op;
}
do_rdrand:
translator_io_start(&s->base);
gen_helper_rdrand(s->T0, cpu_env);
rm = (modrm & 7) | REX_B(s);
@ -5661,9 +5681,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
s->base.is_jmp = DISAS_NORETURN;
break;
case 0x134: /* sysenter */
/* For Intel SYSENTER is valid on 64-bit */
if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
/* For AMD SYSENTER is not valid in long mode */
if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
if (!PE(s)) {
gen_exception_gpf(s);
} else {
@ -5672,19 +5693,22 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
break;
case 0x135: /* sysexit */
/* For Intel SYSEXIT is valid on 64-bit */
if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
/* For AMD SYSEXIT is not valid in long mode */
if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
goto illegal_op;
if (!PE(s)) {
}
if (!PE(s) || CPL(s) != 0) {
gen_exception_gpf(s);
} else {
gen_helper_sysexit(cpu_env, tcg_constant_i32(dflag - 1));
s->base.is_jmp = DISAS_EOB_ONLY;
}
break;
#ifdef TARGET_X86_64
case 0x105: /* syscall */
/* XXX: is it usable in real mode ? */
/* For Intel SYSCALL is only valid in long mode */
if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
gen_update_cc_op(s);
gen_update_eip_cur(s);
gen_helper_syscall(cpu_env, cur_insn_len_i32(s));
@ -5694,7 +5718,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_eob_worker(s, false, true);
break;
case 0x107: /* sysret */
if (!PE(s)) {
/* For Intel SYSRET is only valid in long mode */
if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
if (!PE(s) || CPL(s) != 0) {
gen_exception_gpf(s);
} else {
gen_helper_sysret(cpu_env, tcg_constant_i32(dflag - 1));
@ -5709,7 +5737,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_eob_worker(s, false, true);
}
break;
#endif
case 0x1a2: /* cpuid */
gen_update_cc_op(s);
gen_update_eip_cur(s);
@ -6108,7 +6135,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_cc_op(s);
gen_update_eip_cur(s);
translator_io_start(&s->base);
gen_helper_rdtscp(cpu_env);
gen_helper_rdtsc(cpu_env);
gen_helper_rdpid(s->T0, cpu_env);
gen_op_mov_reg_v(s, dflag, R_ECX, s->T0);
break;
default:
@ -6117,9 +6146,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0x108: /* invd */
case 0x109: /* wbinvd */
case 0x109: /* wbinvd; wbnoinvd with REPZ prefix */
if (check_cpl0(s)) {
gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
gen_svm_check_intercept(s, (b & 1) ? SVM_EXIT_WBINVD : SVM_EXIT_INVD);
/* nothing to do */
}
break;

View File

@ -26,7 +26,6 @@
#include "tcg/helper-tcg.h"
#include "tcg/seg_helper.h"
#ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend)
{
CPUState *cs = env_cpu(env);
@ -36,7 +35,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
env->exception_next_eip = env->eip + next_eip_addend;
cpu_loop_exit(cs);
}
#endif /* TARGET_X86_64 */
/*
* fake user mode interrupt. is_int is TRUE if coming from the int