* 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:
commit
cd041ddbc0
17
Makefile
17
Makefile
|
@ -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 > $@
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>'))
|
||||
|
|
|
@ -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,18 +60,8 @@ 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
|
||||
fi
|
||||
|
||||
if test -n "$maybe_modules" && test -z "$GIT"
|
||||
then
|
||||
echo "$0: unexpectedly called with submodules but git binary not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if is_git; then
|
||||
test -e $substat || touch $substat
|
||||
modules=""
|
||||
for m in $maybe_modules
|
||||
do
|
||||
|
@ -70,23 +69,33 @@ do
|
|||
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
|
||||
|
||||
case "$command" in
|
||||
status|validate)
|
||||
test -f "$substat" || validate_error "$command"
|
||||
test -z "$maybe_modules" && exit 0
|
||||
for module in $modules; do
|
||||
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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue