* 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 \
|
@if test -f meson-private/coredata.dat; then \
|
||||||
./config.status --skip-meson; \
|
./config.status --skip-meson; \
|
||||||
else \
|
else \
|
||||||
./config.status && touch build.ninja.stamp; \
|
./config.status; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 2. meson.stamp exists if meson has run at least once (so ninja reconfigure
|
# 2. meson.stamp exists if meson has run at least once (so ninja reconfigure
|
||||||
# works), but otherwise never needs to be updated
|
# works), but otherwise never needs to be updated
|
||||||
|
|
||||||
meson-private/coredata.dat: meson.stamp
|
meson-private/coredata.dat: meson.stamp
|
||||||
meson.stamp: config-host.mak
|
meson.stamp: config-host.mak
|
||||||
@touch meson.stamp
|
@touch meson.stamp
|
||||||
|
|
||||||
# 3. ensure generated build files are up-to-date
|
# 3. ensure meson-generated build files are up-to-date
|
||||||
|
|
||||||
ifneq ($(NINJA),)
|
ifneq ($(NINJA),)
|
||||||
Makefile.ninja: build.ninja
|
Makefile.ninja: build.ninja
|
||||||
|
@ -106,11 +107,19 @@ Makefile.ninja: build.ninja
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(MESON),)
|
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.ninja: build.ninja.stamp
|
||||||
$(build-files):
|
$(build-files):
|
||||||
build.ninja.stamp: meson.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
|
Makefile.mtest: build.ninja scripts/mtest2make.py
|
||||||
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) 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_init_vcpu: kvm_arch_init_vcpu failed (%lu)",
|
||||||
kvm_arch_vcpu_id(cpu));
|
kvm_arch_vcpu_id(cpu));
|
||||||
}
|
}
|
||||||
|
cpu->kvm_vcpu_stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4007,7 +4009,7 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
|
||||||
|
|
||||||
/* Read stats header */
|
/* Read stats header */
|
||||||
kvm_stats_header = &descriptors->kvm_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)) {
|
if (ret != sizeof(*kvm_stats_header)) {
|
||||||
error_setg(errp, "KVM stats: failed to read stats header: "
|
error_setg(errp, "KVM stats: failed to read stats header: "
|
||||||
"expected %zu actual %zu",
|
"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,
|
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_desc *kvm_stats_desc;
|
||||||
struct kvm_stats_header *kvm_stats_header;
|
struct kvm_stats_header *kvm_stats_header;
|
||||||
|
@ -4096,7 +4099,7 @@ static void query_stats(StatsResultList **result, StatsTarget target,
|
||||||
break;
|
break;
|
||||||
case STATS_TARGET_VCPU:
|
case STATS_TARGET_VCPU:
|
||||||
add_stats_entry(result, STATS_PROVIDER_KVM,
|
add_stats_entry(result, STATS_PROVIDER_KVM,
|
||||||
current_cpu->parent_obj.canonical_path,
|
cpu->parent_obj.canonical_path,
|
||||||
stats_list);
|
stats_list);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -4133,10 +4136,9 @@ static void query_stats_schema(StatsSchemaList **result, StatsTarget target,
|
||||||
add_stats_schema(result, STATS_PROVIDER_KVM, target, stats_list);
|
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 = cpu->kvm_vcpu_stats_fd;
|
||||||
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (stats_fd == -1) {
|
if (stats_fd == -1) {
|
||||||
|
@ -4145,14 +4147,13 @@ static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
query_stats(kvm_stats_args->result.stats, STATS_TARGET_VCPU,
|
query_stats(kvm_stats_args->result.stats, STATS_TARGET_VCPU,
|
||||||
kvm_stats_args->names, stats_fd, kvm_stats_args->errp);
|
kvm_stats_args->names, stats_fd, cpu,
|
||||||
close(stats_fd);
|
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 = cpu->kvm_vcpu_stats_fd;
|
||||||
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (stats_fd == -1) {
|
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,
|
query_stats_schema(kvm_stats_args->result.schema, STATS_TARGET_VCPU, stats_fd,
|
||||||
kvm_stats_args->errp);
|
kvm_stats_args->errp);
|
||||||
close(stats_fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void query_stats_cb(StatsResultList **result, StatsTarget target,
|
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");
|
error_setg_errno(errp, errno, "KVM stats: ioctl failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
query_stats(result, target, names, stats_fd, errp);
|
query_stats(result, target, names, stats_fd, NULL, errp);
|
||||||
close(stats_fd);
|
close(stats_fd);
|
||||||
break;
|
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)) {
|
if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
run_on_cpu(cpu, query_stats_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
|
query_stats_vcpu(cpu, &stats_args);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4220,6 +4220,6 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
|
||||||
if (first_cpu) {
|
if (first_cpu) {
|
||||||
stats_args.result.schema = result;
|
stats_args.result.schema = result;
|
||||||
stats_args.errp = errp;
|
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;
|
break;
|
||||||
|
|
||||||
|
case EXCP_SYSCALL:
|
||||||
|
/* doesn't do anything */
|
||||||
|
break;
|
||||||
|
|
||||||
case EXCP_INTERRUPT:
|
case EXCP_INTERRUPT:
|
||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -758,7 +758,7 @@ done
|
||||||
|
|
||||||
if ! test -e "$source_path/.git"
|
if ! test -e "$source_path/.git"
|
||||||
then
|
then
|
||||||
git_submodules_action="ignore"
|
git_submodules_action="validate"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# test for any invalid configuration combinations
|
# test for any invalid configuration combinations
|
||||||
|
@ -1895,6 +1895,7 @@ if test "$skip_meson" = no; then
|
||||||
if test "$?" -ne 0 ; then
|
if test "$?" -ne 0 ; then
|
||||||
error_exit "meson setup failed"
|
error_exit "meson setup failed"
|
||||||
fi
|
fi
|
||||||
|
echo "$meson" > build.ninja.stamp
|
||||||
else
|
else
|
||||||
if test -f meson-private/cmd_line.txt; then
|
if test -f meson-private/cmd_line.txt; then
|
||||||
# Adjust old command line options that were removed
|
# 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->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;
|
||||||
mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;
|
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;
|
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 = {
|
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->smp_props.clusters_supported = true;
|
||||||
mc->auto_enable_numa_with_memhp = true;
|
mc->auto_enable_numa_with_memhp = true;
|
||||||
mc->auto_enable_numa_with_memdev = 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_ram_id = "mach-virt.ram";
|
||||||
mc->default_nic = "virtio-net-pci";
|
mc->default_nic = "virtio-net-pci";
|
||||||
|
|
||||||
|
|
|
@ -1262,6 +1262,45 @@ static void machine_numa_finish_cpu_init(MachineState *machine)
|
||||||
g_string_free(s, true);
|
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,
|
MemoryRegion *machine_consume_memdev(MachineState *machine,
|
||||||
HostMemoryBackend *backend)
|
HostMemoryBackend *backend)
|
||||||
{
|
{
|
||||||
|
@ -1355,6 +1394,9 @@ void machine_run_board_init(MachineState *machine, const char *mem_path, Error *
|
||||||
numa_complete_configuration(machine);
|
numa_complete_configuration(machine);
|
||||||
if (machine->numa_state->num_nodes) {
|
if (machine->numa_state->num_nodes) {
|
||||||
machine_numa_finish_cpu_init(machine);
|
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 "qom/object.h"
|
||||||
#include "qemu/event_notifier.h"
|
#include "qemu/event_notifier.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "util/event_notifier-posix.c"
|
|
||||||
|
|
||||||
static void probe_pci_info(PCIDevice *dev, Error **errp);
|
static void probe_pci_info(PCIDevice *dev, Error **errp);
|
||||||
static void proxy_device_reset(DeviceState *dev);
|
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->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->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
|
||||||
mc->numa_mem_supported = true;
|
mc->numa_mem_supported = true;
|
||||||
|
/* platform instead of architectural choice */
|
||||||
|
mc->cpu_cluster_has_numa_boundary = true;
|
||||||
mc->default_ram_id = "riscv.spike.ram";
|
mc->default_ram_id = "riscv.spike.ram";
|
||||||
object_class_property_add_str(oc, "signature", NULL, spike_set_signature);
|
object_class_property_add_str(oc, "signature", NULL, spike_set_signature);
|
||||||
object_class_property_set_description(oc, "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->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->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
|
||||||
mc->numa_mem_supported = true;
|
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";
|
mc->default_ram_id = "riscv_virt_board.ram";
|
||||||
assert(!mc->get_hotplug_handler);
|
assert(!mc->get_hotplug_handler);
|
||||||
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
|
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
|
||||||
|
|
|
@ -274,6 +274,7 @@ struct MachineClass {
|
||||||
bool nvdimm_supported;
|
bool nvdimm_supported;
|
||||||
bool numa_mem_supported;
|
bool numa_mem_supported;
|
||||||
bool auto_enable_numa;
|
bool auto_enable_numa;
|
||||||
|
bool cpu_cluster_has_numa_boundary;
|
||||||
SMPCompatProps smp_props;
|
SMPCompatProps smp_props;
|
||||||
const char *default_ram_id;
|
const char *default_ram_id;
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,7 @@ struct CPUState {
|
||||||
struct kvm_dirty_gfn *kvm_dirty_gfns;
|
struct kvm_dirty_gfn *kvm_dirty_gfns;
|
||||||
uint32_t kvm_fetch_index;
|
uint32_t kvm_fetch_index;
|
||||||
uint64_t dirty_pages;
|
uint64_t dirty_pages;
|
||||||
|
int kvm_vcpu_stats_fd;
|
||||||
|
|
||||||
/* Use by accel-block: CPU is executing an ioctl() */
|
/* Use by accel-block: CPU is executing an ioctl() */
|
||||||
QemuLockCnt in_ioctl_lock;
|
QemuLockCnt in_ioctl_lock;
|
||||||
|
|
|
@ -211,6 +211,9 @@ void cpu_loop(CPUX86State *env)
|
||||||
|
|
||||||
switch(trapnr) {
|
switch(trapnr) {
|
||||||
case 0x80:
|
case 0x80:
|
||||||
|
#ifndef TARGET_X86_64
|
||||||
|
case EXCP_SYSCALL:
|
||||||
|
#endif
|
||||||
/* linux syscall from int $0x80 */
|
/* linux syscall from int $0x80 */
|
||||||
ret = do_syscall(env,
|
ret = do_syscall(env,
|
||||||
env->regs[R_EAX],
|
env->regs[R_EAX],
|
||||||
|
@ -227,9 +230,9 @@ void cpu_loop(CPUX86State *env)
|
||||||
env->regs[R_EAX] = ret;
|
env->regs[R_EAX] = ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifndef TARGET_ABI32
|
#ifdef TARGET_X86_64
|
||||||
case EXCP_SYSCALL:
|
case EXCP_SYSCALL:
|
||||||
/* linux syscall from syscall instruction */
|
/* linux syscall from syscall instruction. */
|
||||||
ret = do_syscall(env,
|
ret = do_syscall(env,
|
||||||
env->regs[R_EAX],
|
env->regs[R_EAX],
|
||||||
env->regs[R_EDI],
|
env->regs[R_EDI],
|
||||||
|
@ -245,8 +248,6 @@ void cpu_loop(CPUX86State *env)
|
||||||
env->regs[R_EAX] = ret;
|
env->regs[R_EAX] = ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
case EXCP_VSYSCALL:
|
case EXCP_VSYSCALL:
|
||||||
emulate_vsyscall(env);
|
emulate_vsyscall(env);
|
||||||
break;
|
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_DUP3', cc.has_function('dup3'))
|
||||||
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
|
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_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
|
# Note that we need to specify prefix: here to avoid incorrectly
|
||||||
# thinking that Windows has posix_memalign()
|
# thinking that Windows has posix_memalign()
|
||||||
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
|
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
|
||||||
|
|
|
@ -9,13 +9,22 @@ command=$1
|
||||||
shift
|
shift
|
||||||
maybe_modules="$@"
|
maybe_modules="$@"
|
||||||
|
|
||||||
# if not running in a git checkout, do nothing
|
test -z "$maybe_modules" && exit 0
|
||||||
test "$command" = "ignore" && exit 0
|
|
||||||
|
|
||||||
test -z "$GIT" && GIT=$(command -v git)
|
test -z "$GIT" && GIT=$(command -v git)
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
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() {
|
update_error() {
|
||||||
echo "$0: $*"
|
echo "$0: $*"
|
||||||
echo
|
echo
|
||||||
|
@ -34,7 +43,7 @@ update_error() {
|
||||||
}
|
}
|
||||||
|
|
||||||
validate_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 "GIT submodules checkout is out of date, and submodules"
|
||||||
echo "configured for validate only. Please run"
|
echo "configured for validate only. Please run"
|
||||||
echo " scripts/git-submodule.sh update $maybe_modules"
|
echo " scripts/git-submodule.sh update $maybe_modules"
|
||||||
|
@ -51,18 +60,8 @@ check_updated() {
|
||||||
test "$CURSTATUS" = "$OLDSTATUS"
|
test "$CURSTATUS" = "$OLDSTATUS"
|
||||||
}
|
}
|
||||||
|
|
||||||
if test -n "$maybe_modules" && ! test -e ".git"
|
if is_git; then
|
||||||
then
|
test -e $substat || touch $substat
|
||||||
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
|
|
||||||
|
|
||||||
modules=""
|
modules=""
|
||||||
for m in $maybe_modules
|
for m in $maybe_modules
|
||||||
do
|
do
|
||||||
|
@ -70,23 +69,33 @@ do
|
||||||
if test $? = 0
|
if test $? = 0
|
||||||
then
|
then
|
||||||
modules="$modules $m"
|
modules="$modules $m"
|
||||||
|
grep $m $substat > /dev/null 2>&1 || $GIT submodule status $module >> $substat
|
||||||
else
|
else
|
||||||
echo "warn: ignoring non-existent submodule $m"
|
echo "warn: ignoring non-existent submodule $m"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
else
|
||||||
|
modules=$maybe_modules
|
||||||
|
fi
|
||||||
|
|
||||||
case "$command" in
|
case "$command" in
|
||||||
status|validate)
|
status|validate)
|
||||||
test -f "$substat" || validate_error "$command"
|
|
||||||
test -z "$maybe_modules" && exit 0
|
|
||||||
for module in $modules; do
|
for module in $modules; do
|
||||||
|
if is_git; then
|
||||||
check_updated $module || validate_error "$command"
|
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
|
done
|
||||||
exit 0
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
update)
|
update)
|
||||||
test -e $substat || touch $substat
|
is_git || {
|
||||||
test -z "$maybe_modules" && exit 0
|
echo "$0: unexpectedly called with submodules but $no_git_error"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
$GIT submodule update --init $modules 1>/dev/null
|
$GIT submodule update --init $modules 1>/dev/null
|
||||||
test $? -ne 0 && update_error "failed to update modules"
|
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 */
|
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER */
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
#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
|
#else
|
||||||
#define TCG_EXT2_X86_64_FEATURES 0
|
#define TCG_EXT2_X86_64_FEATURES 0
|
||||||
#endif
|
#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) | \
|
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
|
||||||
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
|
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
|
||||||
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
|
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 | \
|
#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_EXT4_FEATURES 0
|
||||||
#define TCG_SVM_FEATURES (CPUID_SVM_NPT | CPUID_SVM_VGIF | \
|
#define TCG_SVM_FEATURES (CPUID_SVM_NPT | CPUID_SVM_VGIF | \
|
||||||
CPUID_SVM_SVME_ADDR_CHK)
|
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_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_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_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:
|
/* missing:
|
||||||
CPUID_7_0_EBX_HLE
|
CPUID_7_0_EBX_HLE
|
||||||
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
|
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
|
||||||
CPUID_7_0_EBX_RDSEED */
|
|
||||||
|
#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 | \
|
#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_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_0_EDX_FEATURES CPUID_7_0_EDX_FSRM
|
||||||
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
|
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
|
||||||
CPUID_7_1_EAX_FSRC)
|
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_0_EBX_FEATURES 0
|
||||||
#define TCG_SGX_12_1_EAX_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] = {
|
FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||||
[FEAT_1_EDX] = {
|
[FEAT_1_EDX] = {
|
||||||
.type = CPUID_FEATURE_WORD,
|
.type = CPUID_FEATURE_WORD,
|
||||||
|
@ -939,7 +950,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||||
"amd-psfd", NULL, NULL, NULL,
|
"amd-psfd", NULL, NULL, NULL,
|
||||||
},
|
},
|
||||||
.cpuid = { .eax = 0x80000008, .reg = R_EBX, },
|
.cpuid = { .eax = 0x80000008, .reg = R_EBX, },
|
||||||
.tcg_features = 0,
|
.tcg_features = TCG_8000_0008_EBX,
|
||||||
.unmigratable_flags = 0,
|
.unmigratable_flags = 0,
|
||||||
},
|
},
|
||||||
[FEAT_8000_0021_EAX] = {
|
[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 */
|
*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;
|
break;
|
||||||
case 0x80000002:
|
case 0x80000002:
|
||||||
case 0x80000003:
|
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_1(sysenter, void, env)
|
||||||
DEF_HELPER_2(sysexit, void, env, int)
|
DEF_HELPER_2(sysexit, void, env, int)
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
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)
|
||||||
#endif
|
|
||||||
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
|
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_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)
|
||||||
|
@ -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_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
|
||||||
DEF_HELPER_1(rechecking_single_step, void, env)
|
DEF_HELPER_1(rechecking_single_step, void, env)
|
||||||
DEF_HELPER_1(cpuid, 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(rdtsc, void, env)
|
||||||
DEF_HELPER_1(rdtscp, void, env)
|
|
||||||
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
|
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
|
|
@ -75,12 +75,6 @@ void helper_rdtsc(CPUX86State *env)
|
||||||
env->regs[R_EDX] = (uint32_t)(val >> 32);
|
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)
|
G_NORETURN void helper_rdpmc(CPUX86State *env)
|
||||||
{
|
{
|
||||||
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
|
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;
|
env->pkru = val;
|
||||||
tlb_flush(cs);
|
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);
|
e2);
|
||||||
env->eip = offset;
|
env->eip = offset;
|
||||||
}
|
}
|
||||||
|
#endif /* TARGET_X86_64 */
|
||||||
|
|
||||||
void helper_sysret(CPUX86State *env, int dflag)
|
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());
|
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||||
}
|
}
|
||||||
selector = (env->star >> 48) & 0xffff;
|
selector = (env->star >> 48) & 0xffff;
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
if (env->hflags & HF_LMA_MASK) {
|
if (env->hflags & HF_LMA_MASK) {
|
||||||
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
|
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
|
||||||
| ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_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_G_MASK | DESC_B_MASK | DESC_P_MASK |
|
||||||
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
|
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
|
||||||
DESC_W_MASK | DESC_A_MASK);
|
DESC_W_MASK | DESC_A_MASK);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
env->eflags |= IF_MASK;
|
env->eflags |= IF_MASK;
|
||||||
cpu_x86_load_seg_cache(env, R_CS, selector | 3,
|
cpu_x86_load_seg_cache(env, R_CS, selector | 3,
|
||||||
0, 0xffffffff,
|
0, 0xffffffff,
|
||||||
|
@ -1030,7 +1034,6 @@ void helper_sysret(CPUX86State *env, int dflag)
|
||||||
DESC_W_MASK | DESC_A_MASK);
|
DESC_W_MASK | DESC_A_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* TARGET_X86_64 */
|
|
||||||
|
|
||||||
/* real mode interrupt */
|
/* real mode interrupt */
|
||||||
static void do_interrupt_real(CPUX86State *env, int intno, int is_int,
|
static void do_interrupt_real(CPUX86State *env, int intno, int is_int,
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "tcg/helper-tcg.h"
|
#include "tcg/helper-tcg.h"
|
||||||
#include "../seg_helper.h"
|
#include "../seg_helper.h"
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
void helper_syscall(CPUX86State *env, int next_eip_addend)
|
void helper_syscall(CPUX86State *env, int next_eip_addend)
|
||||||
{
|
{
|
||||||
int selector;
|
int selector;
|
||||||
|
@ -35,6 +34,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
|
||||||
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
|
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
|
||||||
}
|
}
|
||||||
selector = (env->star >> 32) & 0xffff;
|
selector = (env->star >> 32) & 0xffff;
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
if (env->hflags & HF_LMA_MASK) {
|
if (env->hflags & HF_LMA_MASK) {
|
||||||
int code64;
|
int code64;
|
||||||
|
|
||||||
|
@ -61,7 +61,9 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
|
||||||
} else {
|
} else {
|
||||||
env->eip = env->cstar;
|
env->eip = env->cstar;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
|
env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
|
||||||
|
|
||||||
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
|
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;
|
env->eip = (uint32_t)env->star;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* TARGET_X86_64 */
|
|
||||||
|
|
||||||
void handle_even_inj(CPUX86State *env, int intno, int is_int,
|
void handle_even_inj(CPUX86State *env, int intno, int is_int,
|
||||||
int error_code, int is_hw, int rm)
|
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);
|
gen_cmpxchg8b(s, env, modrm);
|
||||||
break;
|
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 */
|
case 6: /* RDRAND */
|
||||||
if (mod != 3 ||
|
if (mod != 3 ||
|
||||||
(s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
|
(s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
|
||||||
!(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
|
!(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
|
do_rdrand:
|
||||||
translator_io_start(&s->base);
|
translator_io_start(&s->base);
|
||||||
gen_helper_rdrand(s->T0, cpu_env);
|
gen_helper_rdrand(s->T0, cpu_env);
|
||||||
rm = (modrm & 7) | REX_B(s);
|
rm = (modrm & 7) | REX_B(s);
|
||||||
|
@ -5661,9 +5681,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
||||||
s->base.is_jmp = DISAS_NORETURN;
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
break;
|
break;
|
||||||
case 0x134: /* sysenter */
|
case 0x134: /* sysenter */
|
||||||
/* For Intel SYSENTER is valid on 64-bit */
|
/* For AMD SYSENTER is not valid in long mode */
|
||||||
if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
|
if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
|
}
|
||||||
if (!PE(s)) {
|
if (!PE(s)) {
|
||||||
gen_exception_gpf(s);
|
gen_exception_gpf(s);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5672,19 +5693,22 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x135: /* sysexit */
|
case 0x135: /* sysexit */
|
||||||
/* For Intel SYSEXIT is valid on 64-bit */
|
/* For AMD SYSEXIT is not valid in long mode */
|
||||||
if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
|
if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
if (!PE(s)) {
|
}
|
||||||
|
if (!PE(s) || CPL(s) != 0) {
|
||||||
gen_exception_gpf(s);
|
gen_exception_gpf(s);
|
||||||
} else {
|
} else {
|
||||||
gen_helper_sysexit(cpu_env, tcg_constant_i32(dflag - 1));
|
gen_helper_sysexit(cpu_env, tcg_constant_i32(dflag - 1));
|
||||||
s->base.is_jmp = DISAS_EOB_ONLY;
|
s->base.is_jmp = DISAS_EOB_ONLY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
case 0x105: /* syscall */
|
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_cc_op(s);
|
||||||
gen_update_eip_cur(s);
|
gen_update_eip_cur(s);
|
||||||
gen_helper_syscall(cpu_env, cur_insn_len_i32(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);
|
gen_eob_worker(s, false, true);
|
||||||
break;
|
break;
|
||||||
case 0x107: /* sysret */
|
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);
|
gen_exception_gpf(s);
|
||||||
} else {
|
} else {
|
||||||
gen_helper_sysret(cpu_env, tcg_constant_i32(dflag - 1));
|
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);
|
gen_eob_worker(s, false, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 0x1a2: /* cpuid */
|
case 0x1a2: /* cpuid */
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
gen_update_eip_cur(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_cc_op(s);
|
||||||
gen_update_eip_cur(s);
|
gen_update_eip_cur(s);
|
||||||
translator_io_start(&s->base);
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6117,9 +6146,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x108: /* invd */
|
case 0x108: /* invd */
|
||||||
case 0x109: /* wbinvd */
|
case 0x109: /* wbinvd; wbnoinvd with REPZ prefix */
|
||||||
if (check_cpl0(s)) {
|
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 */
|
/* nothing to do */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "tcg/helper-tcg.h"
|
#include "tcg/helper-tcg.h"
|
||||||
#include "tcg/seg_helper.h"
|
#include "tcg/seg_helper.h"
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
void helper_syscall(CPUX86State *env, int next_eip_addend)
|
void helper_syscall(CPUX86State *env, int next_eip_addend)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
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;
|
env->exception_next_eip = env->eip + next_eip_addend;
|
||||||
cpu_loop_exit(cs);
|
cpu_loop_exit(cs);
|
||||||
}
|
}
|
||||||
#endif /* TARGET_X86_64 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fake user mode interrupt. is_int is TRUE if coming from the int
|
* fake user mode interrupt. is_int is TRUE if coming from the int
|
||||||
|
|
Loading…
Reference in New Issue