x86 and machine queue for 5.0 soft freeze

Bug fixes:
 * memory encryption: Disable mem merge
   (Dr. David Alan Gilbert)
 
 Features:
 * New EPYC CPU definitions (Babu Moger)
 * Denventon-v2 CPU model (Tao Xu)
 * New 'note' field on versioned CPU models (Tao Xu)
 
 Cleanups:
 * x86 CPU topology cleanups (Babu Moger)
 * cpu: Use DeviceClass reset instead of a special CPUClass reset
   (Peter Maydell)
 -----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl5xdnsUHGVoYWJrb3N0
 QHJlZGhhdC5jb20ACgkQKAeTb5hNxaYkGA/9Fn1tCdW/74CEREPbcKNOf8twmCr2
 L4qykix7mFcZXstFhEQuoNJQMz8mEPJngOfUSQY1c9w4psf0AXE6q3wbdNcxxdj1
 1/+cPbaRuoF8EKw63MgR3AaReuWtAV+sGS4+eKBMJTMUbl03pOYARE+irCWJU6rd
 YdP0t6CX0NWF4afv+2wMeeZVr+IcKEo81jCCCSjmM0YLkwvu0Vs5ng3jE7vtFKPj
 MQHMyqD/lz0FwyksBiOLwjOCbnmIydWc/8VV68UH5ulxka96jk8CwmI0+A9v2UMQ
 4PjQ84UeQclJTbec+h/Qy8DoCP3qiqijFMRau2wo1UWCsAjMcaRIJjIe5CSOJFRu
 3FrP2FEJCZiWjh11b/x3jIyjK6MDjv3Y1oky1j5VkCnFUNLHbXUA2KY3jaZ/pf+1
 BDqa6lNDYJBN+FQQt0yXDWAdGLUxxP87S9jmU9RULzwAwCic0FxVR/a5zk9EUDi0
 mA+WL0ekfhIEVACdHYuCTxujGq8QnGiCppr1Wgx3t+GgveR8AjXdd/KclcKskYiw
 ozbujtBPQUImuq3xi6FTkRHXuEW+zc+IFbhZ3Zq5OhmJmpdgmSHryFcKAdvNJH/z
 VllKAsLg1hffm+PjlpuZLBucC4PBrvHbS7htHhMaemEiJHO9V5EfGDWQdELNRM8p
 sKymFNs5XjzQcGE=
 =9fEL
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging

x86 and machine queue for 5.0 soft freeze

Bug fixes:
* memory encryption: Disable mem merge
  (Dr. David Alan Gilbert)

Features:
* New EPYC CPU definitions (Babu Moger)
* Denventon-v2 CPU model (Tao Xu)
* New 'note' field on versioned CPU models (Tao Xu)

Cleanups:
* x86 CPU topology cleanups (Babu Moger)
* cpu: Use DeviceClass reset instead of a special CPUClass reset
  (Peter Maydell)

# gpg: Signature made Wed 18 Mar 2020 01:16:43 GMT
# gpg:                using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6
# gpg:                issuer "ehabkost@redhat.com"
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full]
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/x86-and-machine-pull-request:
  hw/i386: Rename apicid_from_topo_ids to x86_apicid_from_topo_ids
  hw/i386: Update structures to save the number of nodes per package
  hw/i386: Remove unnecessary initialization in x86_cpu_new
  machine: Add SMP Sockets in CpuTopology
  hw/i386: Consolidate topology functions
  hw/i386: Introduce X86CPUTopoInfo to contain topology info
  cpu: Use DeviceClass reset instead of a special CPUClass reset
  machine/memory encryption: Disable mem merge
  hw/i386: Rename X86CPUTopoInfo structure to X86CPUTopoIDs
  i386: Add 2nd Generation AMD EPYC processors
  i386: Add missing cpu feature bits in EPYC model
  target/i386: Add new property note to versioned CPU models
  target/i386: Add Denverton-v2 (no MPX) CPU model

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-03-19 14:22:46 +00:00
commit 4dd6517e36
50 changed files with 485 additions and 274 deletions

View File

@ -239,27 +239,16 @@ void cpu_dump_statistics(CPUState *cpu, int flags)
} }
} }
void cpu_class_set_parent_reset(CPUClass *cc,
void (*child_reset)(CPUState *cpu),
void (**parent_reset)(CPUState *cpu))
{
*parent_reset = cc->reset;
cc->reset = child_reset;
}
void cpu_reset(CPUState *cpu) void cpu_reset(CPUState *cpu)
{ {
CPUClass *klass = CPU_GET_CLASS(cpu); device_cold_reset(DEVICE(cpu));
if (klass->reset != NULL) {
(*klass->reset)(cpu);
}
trace_guest_cpu_reset(cpu); trace_guest_cpu_reset(cpu);
} }
static void cpu_common_reset(CPUState *cpu) static void cpu_common_reset(DeviceState *dev)
{ {
CPUState *cpu = CPU(dev);
CPUClass *cc = CPU_GET_CLASS(cpu); CPUClass *cc = CPU_GET_CLASS(cpu);
if (qemu_loglevel_mask(CPU_LOG_RESET)) { if (qemu_loglevel_mask(CPU_LOG_RESET)) {
@ -419,7 +408,6 @@ static void cpu_class_init(ObjectClass *klass, void *data)
CPUClass *k = CPU_CLASS(klass); CPUClass *k = CPU_CLASS(klass);
k->parse_features = cpu_common_parse_features; k->parse_features = cpu_common_parse_features;
k->reset = cpu_common_reset;
k->get_arch_id = cpu_common_get_arch_id; k->get_arch_id = cpu_common_get_arch_id;
k->has_work = cpu_common_has_work; k->has_work = cpu_common_has_work;
k->get_paging_enabled = cpu_common_get_paging_enabled; k->get_paging_enabled = cpu_common_get_paging_enabled;
@ -440,6 +428,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_CPU, dc->categories); set_bit(DEVICE_CATEGORY_CPU, dc->categories);
dc->realize = cpu_common_realizefn; dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn; dc->unrealize = cpu_common_unrealizefn;
dc->reset = cpu_common_reset;
device_class_set_props(dc, cpu_common_props); device_class_set_props(dc, cpu_common_props);
/* /*
* Reason: CPUs still need special care by board code: wiring up * Reason: CPUs still need special care by board code: wiring up

View File

@ -425,6 +425,14 @@ static void machine_set_memory_encryption(Object *obj, const char *value,
g_free(ms->memory_encryption); g_free(ms->memory_encryption);
ms->memory_encryption = g_strdup(value); ms->memory_encryption = g_strdup(value);
/*
* With memory encryption, the host can't see the real contents of RAM,
* so there's no point in it trying to merge areas.
*/
if (value) {
machine_set_mem_merge(obj, false, errp);
}
} }
static bool machine_get_nvdimm(Object *obj, Error **errp) static bool machine_get_nvdimm(Object *obj, Error **errp)
@ -749,6 +757,7 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
ms->smp.cpus = cpus; ms->smp.cpus = cpus;
ms->smp.cores = cores; ms->smp.cores = cores;
ms->smp.threads = threads; ms->smp.threads = threads;
ms->smp.sockets = sockets;
} }
if (ms->smp.cpus > 1) { if (ms->smp.cpus > 1) {

View File

@ -781,6 +781,7 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)
ms->smp.cpus = cpus; ms->smp.cpus = cpus;
ms->smp.cores = cores; ms->smp.cores = cores;
ms->smp.threads = threads; ms->smp.threads = threads;
ms->smp.sockets = sockets;
x86ms->smp_dies = dies; x86ms->smp_dies = dies;
} }
@ -1505,7 +1506,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
int idx; int idx;
CPUState *cs; CPUState *cs;
CPUArchId *cpu_slot; CPUArchId *cpu_slot;
X86CPUTopoInfo topo; X86CPUTopoIDs topo_ids;
X86CPU *cpu = X86_CPU(dev); X86CPU *cpu = X86_CPU(dev);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MachineState *ms = MACHINE(hotplug_dev); MachineState *ms = MACHINE(hotplug_dev);
@ -1513,6 +1514,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
X86MachineState *x86ms = X86_MACHINE(pcms); X86MachineState *x86ms = X86_MACHINE(pcms);
unsigned int smp_cores = ms->smp.cores; unsigned int smp_cores = ms->smp.cores;
unsigned int smp_threads = ms->smp.threads; unsigned int smp_threads = ms->smp.threads;
X86CPUTopoInfo topo_info;
if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
@ -1520,7 +1522,10 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return; return;
} }
init_topo_info(&topo_info, x86ms);
env->nr_dies = x86ms->smp_dies; env->nr_dies = x86ms->smp_dies;
env->nr_nodes = topo_info.nodes_per_pkg;
/* /*
* If APIC ID is not set, * If APIC ID is not set,
@ -1571,24 +1576,22 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return; return;
} }
topo.pkg_id = cpu->socket_id; topo_ids.pkg_id = cpu->socket_id;
topo.die_id = cpu->die_id; topo_ids.die_id = cpu->die_id;
topo.core_id = cpu->core_id; topo_ids.core_id = cpu->core_id;
topo.smt_id = cpu->thread_id; topo_ids.smt_id = cpu->thread_id;
cpu->apic_id = apicid_from_topo_ids(x86ms->smp_dies, smp_cores, cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids);
smp_threads, &topo);
} }
cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx); cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx);
if (!cpu_slot) { if (!cpu_slot) {
MachineState *ms = MACHINE(pcms); MachineState *ms = MACHINE(pcms);
x86_topo_ids_from_apicid(cpu->apic_id, x86ms->smp_dies, x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
smp_cores, smp_threads, &topo);
error_setg(errp, error_setg(errp,
"Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with" "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
" APIC ID %" PRIu32 ", valid index range 0:%d", " APIC ID %" PRIu32 ", valid index range 0:%d",
topo.pkg_id, topo.die_id, topo.core_id, topo.smt_id, topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id,
cpu->apic_id, ms->possible_cpus->len - 1); cpu->apic_id, ms->possible_cpus->len - 1);
return; return;
} }
@ -1605,35 +1608,37 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
/* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn() /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
* once -smp refactoring is complete and there will be CPU private * once -smp refactoring is complete and there will be CPU private
* CPUState::nr_cores and CPUState::nr_threads fields instead of globals */ * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
x86_topo_ids_from_apicid(cpu->apic_id, x86ms->smp_dies, x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
smp_cores, smp_threads, &topo); if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) {
if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
error_setg(errp, "property socket-id: %u doesn't match set apic-id:" error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
" 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, topo.pkg_id); " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id,
topo_ids.pkg_id);
return; return;
} }
cpu->socket_id = topo.pkg_id; cpu->socket_id = topo_ids.pkg_id;
if (cpu->die_id != -1 && cpu->die_id != topo.die_id) { if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) {
error_setg(errp, "property die-id: %u doesn't match set apic-id:" error_setg(errp, "property die-id: %u doesn't match set apic-id:"
" 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo.die_id); " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id);
return; return;
} }
cpu->die_id = topo.die_id; cpu->die_id = topo_ids.die_id;
if (cpu->core_id != -1 && cpu->core_id != topo.core_id) { if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) {
error_setg(errp, "property core-id: %u doesn't match set apic-id:" error_setg(errp, "property core-id: %u doesn't match set apic-id:"
" 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, topo.core_id); " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id,
topo_ids.core_id);
return; return;
} }
cpu->core_id = topo.core_id; cpu->core_id = topo_ids.core_id;
if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) { if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) {
error_setg(errp, "property thread-id: %u doesn't match set apic-id:" error_setg(errp, "property thread-id: %u doesn't match set apic-id:"
" 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, topo.smt_id); " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id,
topo_ids.smt_id);
return; return;
} }
cpu->thread_id = topo.smt_id; cpu->thread_id = topo_ids.smt_id;
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
!kvm_hv_vpindex_settable()) { !kvm_hv_vpindex_settable()) {

View File

@ -57,6 +57,17 @@
/* Physical Address of PVH entry point read from kernel ELF NOTE */ /* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr; static size_t pvh_start_addr;
inline void init_topo_info(X86CPUTopoInfo *topo_info,
const X86MachineState *x86ms)
{
MachineState *ms = MACHINE(x86ms);
topo_info->nodes_per_pkg = ms->numa_state->num_nodes / ms->smp.sockets;
topo_info->dies_per_pkg = x86ms->smp_dies;
topo_info->cores_per_die = ms->smp.cores;
topo_info->threads_per_core = ms->smp.threads;
}
/* /*
* Calculates initial APIC ID for a specific CPU index * Calculates initial APIC ID for a specific CPU index
* *
@ -68,13 +79,14 @@ static size_t pvh_start_addr;
uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
unsigned int cpu_index) unsigned int cpu_index)
{ {
MachineState *ms = MACHINE(x86ms);
X86MachineClass *x86mc = X86_MACHINE_GET_CLASS(x86ms); X86MachineClass *x86mc = X86_MACHINE_GET_CLASS(x86ms);
X86CPUTopoInfo topo_info;
uint32_t correct_id; uint32_t correct_id;
static bool warned; static bool warned;
correct_id = x86_apicid_from_cpu_idx(x86ms->smp_dies, ms->smp.cores, init_topo_info(&topo_info, x86ms);
ms->smp.threads, cpu_index);
correct_id = x86_apicid_from_cpu_idx(&topo_info, cpu_index);
if (x86mc->compat_apic_id_mode) { if (x86mc->compat_apic_id_mode) {
if (cpu_index != correct_id && !warned && !qtest_enabled()) { if (cpu_index != correct_id && !warned && !qtest_enabled()) {
error_report("APIC IDs set in compatibility mode, " error_report("APIC IDs set in compatibility mode, "
@ -92,13 +104,9 @@ void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
{ {
Object *cpu = NULL; Object *cpu = NULL;
Error *local_err = NULL; Error *local_err = NULL;
CPUX86State *env = NULL;
cpu = object_new(MACHINE(x86ms)->cpu_type); cpu = object_new(MACHINE(x86ms)->cpu_type);
env = &X86_CPU(cpu)->env;
env->nr_dies = x86ms->smp_dies;
object_property_set_uint(cpu, apic_id, "apic-id", &local_err); object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
object_property_set_bool(cpu, true, "realized", &local_err); object_property_set_bool(cpu, true, "realized", &local_err);
@ -143,21 +151,24 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx) int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
{ {
X86CPUTopoInfo topo; X86CPUTopoIDs topo_ids;
X86MachineState *x86ms = X86_MACHINE(ms); X86MachineState *x86ms = X86_MACHINE(ms);
X86CPUTopoInfo topo_info;
init_topo_info(&topo_info, x86ms);
assert(idx < ms->possible_cpus->len); assert(idx < ms->possible_cpus->len);
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id, x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
x86ms->smp_dies, ms->smp.cores, &topo_info, &topo_ids);
ms->smp.threads, &topo); return topo_ids.pkg_id % ms->numa_state->num_nodes;
return topo.pkg_id % ms->numa_state->num_nodes;
} }
const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
{ {
X86MachineState *x86ms = X86_MACHINE(ms); X86MachineState *x86ms = X86_MACHINE(ms);
int i;
unsigned int max_cpus = ms->smp.max_cpus; unsigned int max_cpus = ms->smp.max_cpus;
X86CPUTopoInfo topo_info;
int i;
if (ms->possible_cpus) { if (ms->possible_cpus) {
/* /*
@ -171,26 +182,28 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
sizeof(CPUArchId) * max_cpus); sizeof(CPUArchId) * max_cpus);
ms->possible_cpus->len = max_cpus; ms->possible_cpus->len = max_cpus;
init_topo_info(&topo_info, x86ms);
for (i = 0; i < ms->possible_cpus->len; i++) { for (i = 0; i < ms->possible_cpus->len; i++) {
X86CPUTopoInfo topo; X86CPUTopoIDs topo_ids;
ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].type = ms->cpu_type;
ms->possible_cpus->cpus[i].vcpus_count = 1; ms->possible_cpus->cpus[i].vcpus_count = 1;
ms->possible_cpus->cpus[i].arch_id = ms->possible_cpus->cpus[i].arch_id =
x86_cpu_apic_id_from_index(x86ms, i); x86_cpu_apic_id_from_index(x86ms, i);
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
x86ms->smp_dies, ms->smp.cores, &topo_info, &topo_ids);
ms->smp.threads, &topo);
ms->possible_cpus->cpus[i].props.has_socket_id = true; ms->possible_cpus->cpus[i].props.has_socket_id = true;
ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id; ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id;
if (x86ms->smp_dies > 1) { if (x86ms->smp_dies > 1) {
ms->possible_cpus->cpus[i].props.has_die_id = true; ms->possible_cpus->cpus[i].props.has_die_id = true;
ms->possible_cpus->cpus[i].props.die_id = topo.die_id; ms->possible_cpus->cpus[i].props.die_id = topo_ids.die_id;
} }
ms->possible_cpus->cpus[i].props.has_core_id = true; ms->possible_cpus->cpus[i].props.has_core_id = true;
ms->possible_cpus->cpus[i].props.core_id = topo.core_id; ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id;
ms->possible_cpus->cpus[i].props.has_thread_id = true; ms->possible_cpus->cpus[i].props.has_thread_id = true;
ms->possible_cpus->cpus[i].props.thread_id = topo.smt_id; ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id;
} }
return ms->possible_cpus; return ms->possible_cpus;
} }

View File

@ -236,12 +236,14 @@ typedef struct DeviceMemoryState {
* @cpus: the number of present logical processors on the machine * @cpus: the number of present logical processors on the machine
* @cores: the number of cores in one package * @cores: the number of cores in one package
* @threads: the number of threads in one core * @threads: the number of threads in one core
* @sockets: the number of sockets on the machine
* @max_cpus: the maximum number of logical processors on the machine * @max_cpus: the maximum number of logical processors on the machine
*/ */
typedef struct CpuTopology { typedef struct CpuTopology {
unsigned int cpus; unsigned int cpus;
unsigned int cores; unsigned int cores;
unsigned int threads; unsigned int threads;
unsigned int sockets;
unsigned int max_cpus; unsigned int max_cpus;
} CpuTopology; } CpuTopology;

View File

@ -79,7 +79,6 @@ struct TranslationBlock;
* @class_by_name: Callback to map -cpu command line model name to an * @class_by_name: Callback to map -cpu command line model name to an
* instantiatable CPU type. * instantiatable CPU type.
* @parse_features: Callback to parse command line arguments. * @parse_features: Callback to parse command line arguments.
* @reset: Callback to reset the #CPUState to its initial state.
* @reset_dump_flags: #CPUDumpFlags to use for reset logging. * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
* @has_work: Callback for checking if there is work to do. * @has_work: Callback for checking if there is work to do.
* @do_interrupt: Callback for interrupt handling. * @do_interrupt: Callback for interrupt handling.
@ -165,7 +164,6 @@ typedef struct CPUClass {
ObjectClass *(*class_by_name)(const char *cpu_model); ObjectClass *(*class_by_name)(const char *cpu_model);
void (*parse_features)(const char *typename, char *str, Error **errp); void (*parse_features)(const char *typename, char *str, Error **errp);
void (*reset)(CPUState *cpu);
int reset_dump_flags; int reset_dump_flags;
bool (*has_work)(CPUState *cpu); bool (*has_work)(CPUState *cpu);
void (*do_interrupt)(CPUState *cpu); void (*do_interrupt)(CPUState *cpu);
@ -1135,10 +1133,6 @@ void cpu_exec_unrealizefn(CPUState *cpu);
*/ */
bool target_words_bigendian(void); bool target_words_bigendian(void);
void cpu_class_set_parent_reset(CPUClass *cc,
void (*child_reset)(CPUState *cpu),
void (**parent_reset)(CPUState *cpu));
#ifdef NEED_CPU_H #ifdef NEED_CPU_H
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU

View File

@ -45,11 +45,18 @@
*/ */
typedef uint32_t apic_id_t; typedef uint32_t apic_id_t;
typedef struct X86CPUTopoInfo { typedef struct X86CPUTopoIDs {
unsigned pkg_id; unsigned pkg_id;
unsigned die_id; unsigned die_id;
unsigned core_id; unsigned core_id;
unsigned smt_id; unsigned smt_id;
} X86CPUTopoIDs;
typedef struct X86CPUTopoInfo {
unsigned nodes_per_pkg;
unsigned dies_per_pkg;
unsigned cores_per_die;
unsigned threads_per_core;
} X86CPUTopoInfo; } X86CPUTopoInfo;
/* Return the bit width needed for 'count' IDs /* Return the bit width needed for 'count' IDs
@ -63,120 +70,102 @@ static unsigned apicid_bitwidth_for_count(unsigned count)
/* Bit width of the SMT_ID (thread ID) field on the APIC ID /* Bit width of the SMT_ID (thread ID) field on the APIC ID
*/ */
static inline unsigned apicid_smt_width(unsigned nr_dies, static inline unsigned apicid_smt_width(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_bitwidth_for_count(nr_threads); return apicid_bitwidth_for_count(topo_info->threads_per_core);
} }
/* Bit width of the Core_ID field /* Bit width of the Core_ID field
*/ */
static inline unsigned apicid_core_width(unsigned nr_dies, static inline unsigned apicid_core_width(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_bitwidth_for_count(nr_cores); return apicid_bitwidth_for_count(topo_info->cores_per_die);
} }
/* Bit width of the Die_ID field */ /* Bit width of the Die_ID field */
static inline unsigned apicid_die_width(unsigned nr_dies, static inline unsigned apicid_die_width(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_bitwidth_for_count(nr_dies); return apicid_bitwidth_for_count(topo_info->dies_per_pkg);
} }
/* Bit offset of the Core_ID field /* Bit offset of the Core_ID field
*/ */
static inline unsigned apicid_core_offset(unsigned nr_dies, static inline unsigned apicid_core_offset(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_smt_width(nr_dies, nr_cores, nr_threads); return apicid_smt_width(topo_info);
} }
/* Bit offset of the Die_ID field */ /* Bit offset of the Die_ID field */
static inline unsigned apicid_die_offset(unsigned nr_dies, static inline unsigned apicid_die_offset(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_core_offset(nr_dies, nr_cores, nr_threads) + return apicid_core_offset(topo_info) + apicid_core_width(topo_info);
apicid_core_width(nr_dies, nr_cores, nr_threads);
} }
/* Bit offset of the Pkg_ID (socket ID) field /* Bit offset of the Pkg_ID (socket ID) field
*/ */
static inline unsigned apicid_pkg_offset(unsigned nr_dies, static inline unsigned apicid_pkg_offset(X86CPUTopoInfo *topo_info)
unsigned nr_cores,
unsigned nr_threads)
{ {
return apicid_die_offset(nr_dies, nr_cores, nr_threads) + return apicid_die_offset(topo_info) + apicid_die_width(topo_info);
apicid_die_width(nr_dies, nr_cores, nr_threads);
} }
/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID /* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID
* *
* The caller must make sure core_id < nr_cores and smt_id < nr_threads. * The caller must make sure core_id < nr_cores and smt_id < nr_threads.
*/ */
static inline apic_id_t apicid_from_topo_ids(unsigned nr_dies, static inline apic_id_t x86_apicid_from_topo_ids(X86CPUTopoInfo *topo_info,
unsigned nr_cores, const X86CPUTopoIDs *topo_ids)
unsigned nr_threads,
const X86CPUTopoInfo *topo)
{ {
return (topo->pkg_id << apicid_pkg_offset(nr_dies, nr_cores, nr_threads)) | return (topo_ids->pkg_id << apicid_pkg_offset(topo_info)) |
(topo->die_id << apicid_die_offset(nr_dies, nr_cores, nr_threads)) | (topo_ids->die_id << apicid_die_offset(topo_info)) |
(topo->core_id << apicid_core_offset(nr_dies, nr_cores, nr_threads)) | (topo_ids->core_id << apicid_core_offset(topo_info)) |
topo->smt_id; topo_ids->smt_id;
} }
/* Calculate thread/core/package IDs for a specific topology, /* Calculate thread/core/package IDs for a specific topology,
* based on (contiguous) CPU index * based on (contiguous) CPU index
*/ */
static inline void x86_topo_ids_from_idx(unsigned nr_dies, static inline void x86_topo_ids_from_idx(X86CPUTopoInfo *topo_info,
unsigned nr_cores,
unsigned nr_threads,
unsigned cpu_index, unsigned cpu_index,
X86CPUTopoInfo *topo) X86CPUTopoIDs *topo_ids)
{ {
topo->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads); unsigned nr_dies = topo_info->dies_per_pkg;
topo->die_id = cpu_index / (nr_cores * nr_threads) % nr_dies; unsigned nr_cores = topo_info->cores_per_die;
topo->core_id = cpu_index / nr_threads % nr_cores; unsigned nr_threads = topo_info->threads_per_core;
topo->smt_id = cpu_index % nr_threads;
topo_ids->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads);
topo_ids->die_id = cpu_index / (nr_cores * nr_threads) % nr_dies;
topo_ids->core_id = cpu_index / nr_threads % nr_cores;
topo_ids->smt_id = cpu_index % nr_threads;
} }
/* Calculate thread/core/package IDs for a specific topology, /* Calculate thread/core/package IDs for a specific topology,
* based on APIC ID * based on APIC ID
*/ */
static inline void x86_topo_ids_from_apicid(apic_id_t apicid, static inline void x86_topo_ids_from_apicid(apic_id_t apicid,
unsigned nr_dies, X86CPUTopoInfo *topo_info,
unsigned nr_cores, X86CPUTopoIDs *topo_ids)
unsigned nr_threads,
X86CPUTopoInfo *topo)
{ {
topo->smt_id = apicid & topo_ids->smt_id = apicid &
~(0xFFFFFFFFUL << apicid_smt_width(nr_dies, nr_cores, nr_threads)); ~(0xFFFFFFFFUL << apicid_smt_width(topo_info));
topo->core_id = topo_ids->core_id =
(apicid >> apicid_core_offset(nr_dies, nr_cores, nr_threads)) & (apicid >> apicid_core_offset(topo_info)) &
~(0xFFFFFFFFUL << apicid_core_width(nr_dies, nr_cores, nr_threads)); ~(0xFFFFFFFFUL << apicid_core_width(topo_info));
topo->die_id = topo_ids->die_id =
(apicid >> apicid_die_offset(nr_dies, nr_cores, nr_threads)) & (apicid >> apicid_die_offset(topo_info)) &
~(0xFFFFFFFFUL << apicid_die_width(nr_dies, nr_cores, nr_threads)); ~(0xFFFFFFFFUL << apicid_die_width(topo_info));
topo->pkg_id = apicid >> apicid_pkg_offset(nr_dies, nr_cores, nr_threads); topo_ids->pkg_id = apicid >> apicid_pkg_offset(topo_info);
} }
/* Make APIC ID for the CPU 'cpu_index' /* Make APIC ID for the CPU 'cpu_index'
* *
* 'cpu_index' is a sequential, contiguous ID for the CPU. * 'cpu_index' is a sequential, contiguous ID for the CPU.
*/ */
static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_dies, static inline apic_id_t x86_apicid_from_cpu_idx(X86CPUTopoInfo *topo_info,
unsigned nr_cores,
unsigned nr_threads,
unsigned cpu_index) unsigned cpu_index)
{ {
X86CPUTopoInfo topo; X86CPUTopoIDs topo_ids;
x86_topo_ids_from_idx(nr_dies, nr_cores, nr_threads, cpu_index, &topo); x86_topo_ids_from_idx(topo_info, cpu_index, &topo_ids);
return apicid_from_topo_ids(nr_dies, nr_cores, nr_threads, &topo); return x86_apicid_from_topo_ids(topo_info, &topo_ids);
} }
#endif /* HW_I386_TOPOLOGY_H */ #endif /* HW_I386_TOPOLOGY_H */

View File

@ -21,6 +21,7 @@
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include "qemu/notify.h" #include "qemu/notify.h"
#include "hw/i386/topology.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/nmi.h" #include "hw/nmi.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
@ -82,6 +83,8 @@ typedef struct {
#define X86_MACHINE_CLASS(class) \ #define X86_MACHINE_CLASS(class) \
OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE) OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE)
void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms, uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
unsigned int cpu_index); unsigned int cpu_index);

View File

@ -0,0 +1,47 @@
// Convert targets using the old CPUState reset to DeviceState reset
//
// Copyright Linaro Ltd 2020
// This work is licensed under the terms of the GNU GPLv2 or later.
//
// spatch --macro-file scripts/cocci-macro-file.h \
// --sp-file scripts/coccinelle/cpu-reset.cocci \
// --keep-comments --smpl-spacing --in-place --include-headers --dir target
//
// For simplicity we assume some things about the code we're modifying
// that happen to be true for all our targets:
// * all cpu_class_set_parent_reset() callsites have a 'DeviceClass *dc' local
// * the parent reset field in the target CPU class is 'parent_reset'
// * no reset function already has a 'dev' local
@@
identifier cpu, x;
typedef CPUState;
@@
struct x {
...
- void (*parent_reset)(CPUState *cpu);
+ DeviceReset parent_reset;
...
};
@ rule1 @
identifier resetfn;
expression resetfield;
identifier cc;
@@
- cpu_class_set_parent_reset(cc, resetfn, resetfield)
+ device_class_set_parent_reset(dc, resetfn, resetfield)
@@
identifier rule1.resetfn;
identifier cpu, cc;
typedef CPUState, DeviceState;
@@
-resetfn(CPUState *cpu)
-{
+resetfn(DeviceState *dev)
+{
+ CPUState *cpu = CPU(dev);
<...
- cc->parent_reset(cpu);
+ cc->parent_reset(dev);
...>
}

View File

@ -3946,6 +3946,7 @@ void qemu_init(int argc, char **argv, char **envp)
current_machine->smp.max_cpus = machine_class->default_cpus; current_machine->smp.max_cpus = machine_class->default_cpus;
current_machine->smp.cores = 1; current_machine->smp.cores = 1;
current_machine->smp.threads = 1; current_machine->smp.threads = 1;
current_machine->smp.sockets = 1;
machine_class->smp_parse(current_machine, machine_class->smp_parse(current_machine,
qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); qemu_opts_find(qemu_find_opts("smp-opts"), NULL));

View File

@ -44,7 +44,7 @@ typedef struct AlphaCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} AlphaCPUClass; } AlphaCPUClass;
typedef struct AlphaCPU AlphaCPU; typedef struct AlphaCPU AlphaCPU;

View File

@ -51,7 +51,7 @@ typedef struct ARMCPUClass {
const ARMCPUInfo *info; const ARMCPUInfo *info;
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} ARMCPUClass; } ARMCPUClass;
typedef struct ARMCPU ARMCPU; typedef struct ARMCPU ARMCPU;

View File

@ -155,14 +155,14 @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
assert(oldvalue == newvalue); assert(oldvalue == newvalue);
} }
/* CPUClass::reset() */ static void arm_cpu_reset(DeviceState *dev)
static void arm_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
ARMCPU *cpu = ARM_CPU(s); ARMCPU *cpu = ARM_CPU(s);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu); ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
acc->parent_reset(s); acc->parent_reset(dev);
memset(env, 0, offsetof(CPUARMState, end_reset_fields)); memset(env, 0, offsetof(CPUARMState, end_reset_fields));
@ -2786,7 +2786,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
&acc->parent_realize); &acc->parent_realize);
device_class_set_props(dc, arm_cpu_properties); device_class_set_props(dc, arm_cpu_properties);
cpu_class_set_parent_reset(cc, arm_cpu_reset, &acc->parent_reset); device_class_set_parent_reset(dc, arm_cpu_reset, &acc->parent_reset);
cc->class_by_name = arm_cpu_class_by_name; cc->class_by_name = arm_cpu_class_by_name;
cc->has_work = arm_cpu_has_work; cc->has_work = arm_cpu_has_work;

View File

@ -45,7 +45,7 @@ typedef struct CRISCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
uint32_t vr; uint32_t vr;
} CRISCPUClass; } CRISCPUClass;

View File

@ -40,15 +40,15 @@ static bool cris_cpu_has_work(CPUState *cs)
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
} }
/* CPUClass::reset() */ static void cris_cpu_reset(DeviceState *dev)
static void cris_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
CRISCPU *cpu = CRIS_CPU(s); CRISCPU *cpu = CRIS_CPU(s);
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(cpu); CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(cpu);
CPUCRISState *env = &cpu->env; CPUCRISState *env = &cpu->env;
uint32_t vr; uint32_t vr;
ccc->parent_reset(s); ccc->parent_reset(dev);
vr = env->pregs[PR_VR]; vr = env->pregs[PR_VR];
memset(env, 0, offsetof(CPUCRISState, end_reset_fields)); memset(env, 0, offsetof(CPUCRISState, end_reset_fields));
@ -264,7 +264,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, cris_cpu_realizefn, device_class_set_parent_realize(dc, cris_cpu_realizefn,
&ccc->parent_realize); &ccc->parent_realize);
cpu_class_set_parent_reset(cc, cris_cpu_reset, &ccc->parent_reset); device_class_set_parent_reset(dc, cris_cpu_reset, &ccc->parent_reset);
cc->class_by_name = cris_cpu_class_by_name; cc->class_by_name = cris_cpu_class_by_name;
cc->has_work = cris_cpu_has_work; cc->has_work = cris_cpu_has_work;

View File

@ -44,7 +44,7 @@ typedef struct HPPACPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} HPPACPUClass; } HPPACPUClass;
typedef struct HPPACPU HPPACPU; typedef struct HPPACPU HPPACPU;

View File

@ -71,7 +71,7 @@ typedef struct X86CPUClass {
DeviceRealize parent_realize; DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize; DeviceUnrealize parent_unrealize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} X86CPUClass; } X86CPUClass;
typedef struct X86CPU X86CPU; typedef struct X86CPU X86CPU;

View File

@ -1133,7 +1133,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"clzero", NULL, "xsaveerptr", NULL, "clzero", NULL, "xsaveerptr", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "wbnoinvd", NULL, NULL, NULL, "wbnoinvd", NULL, NULL,
"ibpb", NULL, NULL, NULL, "ibpb", NULL, NULL, "amd-stibp",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL, "amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL,
@ -1690,6 +1690,7 @@ typedef struct PropValue {
typedef struct X86CPUVersionDefinition { typedef struct X86CPUVersionDefinition {
X86CPUVersion version; X86CPUVersion version;
const char *alias; const char *alias;
const char *note;
PropValue *props; PropValue *props;
} X86CPUVersionDefinition; } X86CPUVersionDefinition;
@ -1720,6 +1721,7 @@ struct X86CPUModel {
X86CPUDefinition *cpudef; X86CPUDefinition *cpudef;
/* CPU model version */ /* CPU model version */
X86CPUVersion version; X86CPUVersion version;
const char *note;
/* /*
* If true, this is an alias CPU model. * If true, this is an alias CPU model.
* This matters only for "-cpu help" and query-cpu-definitions * This matters only for "-cpu help" and query-cpu-definitions
@ -1796,6 +1798,56 @@ static CPUCaches epyc_cache_info = {
}, },
}; };
static CPUCaches epyc_rome_cache_info = {
.l1d_cache = &(CPUCacheInfo) {
.type = DATA_CACHE,
.level = 1,
.size = 32 * KiB,
.line_size = 64,
.associativity = 8,
.partitions = 1,
.sets = 64,
.lines_per_tag = 1,
.self_init = 1,
.no_invd_sharing = true,
},
.l1i_cache = &(CPUCacheInfo) {
.type = INSTRUCTION_CACHE,
.level = 1,
.size = 32 * KiB,
.line_size = 64,
.associativity = 8,
.partitions = 1,
.sets = 64,
.lines_per_tag = 1,
.self_init = 1,
.no_invd_sharing = true,
},
.l2_cache = &(CPUCacheInfo) {
.type = UNIFIED_CACHE,
.level = 2,
.size = 512 * KiB,
.line_size = 64,
.associativity = 8,
.partitions = 1,
.sets = 1024,
.lines_per_tag = 1,
},
.l3_cache = &(CPUCacheInfo) {
.type = UNIFIED_CACHE,
.level = 3,
.size = 16 * MiB,
.line_size = 64,
.associativity = 16,
.partitions = 1,
.sets = 16384,
.lines_per_tag = 1,
.self_init = true,
.inclusive = true,
.complex_indexing = true,
},
};
/* The following VMX features are not supported by KVM and are left out in the /* The following VMX features are not supported by KVM and are left out in the
* CPU definitions: * CPU definitions:
* *
@ -3592,6 +3644,18 @@ static X86CPUDefinition builtin_x86_defs[] = {
.features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING,
.xlevel = 0x80000008, .xlevel = 0x80000008,
.model_id = "Intel Atom Processor (Denverton)", .model_id = "Intel Atom Processor (Denverton)",
.versions = (X86CPUVersionDefinition[]) {
{ .version = 1 },
{
.version = 2,
.props = (PropValue[]) {
{ "monitor", "off" },
{ "mpx", "off" },
{ /* end of list */ },
},
},
{ /* end of list */ },
},
}, },
{ {
.name = "Snowridge", .name = "Snowridge",
@ -3928,10 +3992,6 @@ static X86CPUDefinition builtin_x86_defs[] = {
CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED |
CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT |
CPUID_7_0_EBX_SHA_NI, CPUID_7_0_EBX_SHA_NI,
/* Missing: XSAVES (not supported by some Linux versions,
* including v4.1 to v4.12).
* KVM doesn't yet expose any XSAVES state save component.
*/
.features[FEAT_XSAVE] = .features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
CPUID_XSAVE_XGETBV1, CPUID_XSAVE_XGETBV1,
@ -3954,6 +4014,19 @@ static X86CPUDefinition builtin_x86_defs[] = {
{ /* end of list */ } { /* end of list */ }
} }
}, },
{
.version = 3,
.props = (PropValue[]) {
{ "ibpb", "on" },
{ "perfctr-core", "on" },
{ "clzero", "on" },
{ "xsaveerptr", "on" },
{ "xsaves", "on" },
{ "model-id",
"AMD EPYC Processor" },
{ /* end of list */ }
}
},
{ /* end of list */ } { /* end of list */ }
} }
}, },
@ -4007,6 +4080,56 @@ static X86CPUDefinition builtin_x86_defs[] = {
.model_id = "Hygon Dhyana Processor", .model_id = "Hygon Dhyana Processor",
.cache_info = &epyc_cache_info, .cache_info = &epyc_cache_info,
}, },
{
.name = "EPYC-Rome",
.level = 0xd,
.vendor = CPUID_VENDOR_AMD,
.family = 23,
.model = 49,
.stepping = 0,
.features[FEAT_1_EDX] =
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH |
CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE |
CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE |
CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE |
CPUID_VME | CPUID_FP87,
.features[FEAT_1_ECX] =
CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX |
CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT |
CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 |
CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
.features[FEAT_8000_0001_EDX] =
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB |
CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH |
CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM |
CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM |
CPUID_EXT3_TOPOEXT | CPUID_EXT3_PERFCORE,
.features[FEAT_8000_0008_EBX] =
CPUID_8000_0008_EBX_CLZERO | CPUID_8000_0008_EBX_XSAVEERPTR |
CPUID_8000_0008_EBX_WBNOINVD | CPUID_8000_0008_EBX_IBPB |
CPUID_8000_0008_EBX_STIBP,
.features[FEAT_7_0_EBX] =
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 |
CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED |
CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT |
CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_CLWB,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_RDPID,
.features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
.features[FEAT_SVM] =
CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE,
.xlevel = 0x8000001E,
.model_id = "AMD EPYC-Rome Processor",
.cache_info = &epyc_rome_cache_info,
},
}; };
/* KVM-specific features that are automatically added/removed /* KVM-specific features that are automatically added/removed
@ -4849,6 +4972,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data)
g_autofree char *name = x86_cpu_class_get_model_name(cc); g_autofree char *name = x86_cpu_class_get_model_name(cc);
g_autofree char *desc = g_strdup(cc->model_description); g_autofree char *desc = g_strdup(cc->model_description);
g_autofree char *alias_of = x86_cpu_class_get_alias_of(cc); g_autofree char *alias_of = x86_cpu_class_get_alias_of(cc);
g_autofree char *model_id = x86_cpu_class_get_model_id(cc);
if (!desc && alias_of) { if (!desc && alias_of) {
if (cc->model && cc->model->version == CPU_VERSION_AUTO) { if (cc->model && cc->model->version == CPU_VERSION_AUTO) {
@ -4857,11 +4981,14 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data)
desc = g_strdup_printf("(alias of %s)", alias_of); desc = g_strdup_printf("(alias of %s)", alias_of);
} }
} }
if (!desc && cc->model && cc->model->note) {
desc = g_strdup_printf("%s [%s]", model_id, cc->model->note);
}
if (!desc) { if (!desc) {
desc = x86_cpu_class_get_model_id(cc); desc = g_strdup_printf("%s", model_id);
} }
qemu_printf("x86 %-20s %-48s\n", name, desc); qemu_printf("x86 %-20s %-58s\n", name, desc);
} }
/* list available CPU models and flags */ /* list available CPU models and flags */
@ -5338,6 +5465,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
x86_cpu_versioned_model_name(def, vdef->version); x86_cpu_versioned_model_name(def, vdef->version);
m->cpudef = def; m->cpudef = def;
m->version = vdef->version; m->version = vdef->version;
m->note = vdef->note;
x86_register_cpu_model_type(name, m); x86_register_cpu_model_type(name, m);
if (vdef->alias) { if (vdef->alias) {
@ -5369,6 +5497,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t die_offset; uint32_t die_offset;
uint32_t limit; uint32_t limit;
uint32_t signature[3]; uint32_t signature[3];
X86CPUTopoInfo topo_info;
topo_info.dies_per_pkg = env->nr_dies;
topo_info.cores_per_die = cs->nr_cores;
topo_info.threads_per_core = cs->nr_threads;
/* Calculate & apply limits for different index ranges */ /* Calculate & apply limits for different index ranges */
if (index >= 0xC0000000) { if (index >= 0xC0000000) {
@ -5455,8 +5588,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
eax, ebx, ecx, edx); eax, ebx, ecx, edx);
break; break;
case 3: /* L3 cache info */ case 3: /* L3 cache info */
die_offset = apicid_die_offset(env->nr_dies, die_offset = apicid_die_offset(&topo_info);
cs->nr_cores, cs->nr_threads);
if (cpu->enable_l3_cache) { if (cpu->enable_l3_cache) {
encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache,
(1 << die_offset), cs->nr_cores, (1 << die_offset), cs->nr_cores,
@ -5547,14 +5679,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch (count) { switch (count) {
case 0: case 0:
*eax = apicid_core_offset(env->nr_dies, *eax = apicid_core_offset(&topo_info);
cs->nr_cores, cs->nr_threads);
*ebx = cs->nr_threads; *ebx = cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT; *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
break; break;
case 1: case 1:
*eax = apicid_pkg_offset(env->nr_dies, *eax = apicid_pkg_offset(&topo_info);
cs->nr_cores, cs->nr_threads);
*ebx = cs->nr_cores * cs->nr_threads; *ebx = cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE; *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
break; break;
@ -5578,20 +5708,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = cpu->apic_id; *edx = cpu->apic_id;
switch (count) { switch (count) {
case 0: case 0:
*eax = apicid_core_offset(env->nr_dies, cs->nr_cores, *eax = apicid_core_offset(&topo_info);
cs->nr_threads);
*ebx = cs->nr_threads; *ebx = cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT; *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
break; break;
case 1: case 1:
*eax = apicid_die_offset(env->nr_dies, cs->nr_cores, *eax = apicid_die_offset(&topo_info);
cs->nr_threads);
*ebx = cs->nr_cores * cs->nr_threads; *ebx = cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE; *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
break; break;
case 2: case 2:
*eax = apicid_pkg_offset(env->nr_dies, cs->nr_cores, *eax = apicid_pkg_offset(&topo_info);
cs->nr_threads);
*ebx = env->nr_dies * cs->nr_cores * cs->nr_threads; *ebx = env->nr_dies * cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_DIE; *ecx |= CPUID_TOPOLOGY_LEVEL_DIE;
break; break;
@ -5855,9 +5982,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
} }
} }
/* CPUClass::reset() */ static void x86_cpu_reset(DeviceState *dev)
static void x86_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
X86CPU *cpu = X86_CPU(s); X86CPU *cpu = X86_CPU(s);
X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu); X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
@ -5865,7 +5992,7 @@ static void x86_cpu_reset(CPUState *s)
uint64_t xcr0; uint64_t xcr0;
int i; int i;
xcc->parent_reset(s); xcc->parent_reset(dev);
memset(env, 0, offsetof(CPUX86State, end_reset_fields)); memset(env, 0, offsetof(CPUX86State, end_reset_fields));
@ -6830,6 +6957,7 @@ static void x86_cpu_initfn(Object *obj)
FeatureWord w; FeatureWord w;
env->nr_dies = 1; env->nr_dies = 1;
env->nr_nodes = 1;
cpu_set_cpustate_pointers(cpu); cpu_set_cpustate_pointers(cpu);
object_property_add(obj, "family", "int", object_property_add(obj, "family", "int",
@ -7169,7 +7297,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
&xcc->parent_unrealize); &xcc->parent_unrealize);
device_class_set_props(dc, x86_cpu_properties); device_class_set_props(dc, x86_cpu_properties);
cpu_class_set_parent_reset(cc, x86_cpu_reset, &xcc->parent_reset); device_class_set_parent_reset(dc, x86_cpu_reset, &xcc->parent_reset);
cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP; cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
cc->class_by_name = x86_cpu_class_by_name; cc->class_by_name = x86_cpu_class_by_name;

View File

@ -792,6 +792,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9)
/* Indirect Branch Prediction Barrier */ /* Indirect Branch Prediction Barrier */
#define CPUID_8000_0008_EBX_IBPB (1U << 12) #define CPUID_8000_0008_EBX_IBPB (1U << 12)
/* Single Thread Indirect Branch Predictors */
#define CPUID_8000_0008_EBX_STIBP (1U << 15)
#define CPUID_XSAVE_XSAVEOPT (1U << 0) #define CPUID_XSAVE_XSAVEOPT (1U << 0)
#define CPUID_XSAVE_XSAVEC (1U << 1) #define CPUID_XSAVE_XSAVEC (1U << 1)
@ -1607,6 +1609,7 @@ typedef struct CPUX86State {
TPRAccess tpr_access_type; TPRAccess tpr_access_type;
unsigned nr_dies; unsigned nr_dies;
unsigned nr_nodes;
} CPUX86State; } CPUX86State;
struct kvm_msrs; struct kvm_msrs;

View File

@ -44,7 +44,7 @@ typedef struct LM32CPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} LM32CPUClass; } LM32CPUClass;
typedef struct LM32CPU LM32CPU; typedef struct LM32CPU LM32CPU;

View File

@ -99,14 +99,14 @@ static bool lm32_cpu_has_work(CPUState *cs)
return cs->interrupt_request & CPU_INTERRUPT_HARD; return cs->interrupt_request & CPU_INTERRUPT_HARD;
} }
/* CPUClass::reset() */ static void lm32_cpu_reset(DeviceState *dev)
static void lm32_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
LM32CPU *cpu = LM32_CPU(s); LM32CPU *cpu = LM32_CPU(s);
LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu); LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
CPULM32State *env = &cpu->env; CPULM32State *env = &cpu->env;
lcc->parent_reset(s); lcc->parent_reset(dev);
/* reset cpu state */ /* reset cpu state */
memset(env, 0, offsetof(CPULM32State, end_reset_fields)); memset(env, 0, offsetof(CPULM32State, end_reset_fields));
@ -218,7 +218,7 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, lm32_cpu_realizefn, device_class_set_parent_realize(dc, lm32_cpu_realizefn,
&lcc->parent_realize); &lcc->parent_realize);
cpu_class_set_parent_reset(cc, lm32_cpu_reset, &lcc->parent_reset); device_class_set_parent_reset(dc, lm32_cpu_reset, &lcc->parent_reset);
cc->class_by_name = lm32_cpu_class_by_name; cc->class_by_name = lm32_cpu_class_by_name;
cc->has_work = lm32_cpu_has_work; cc->has_work = lm32_cpu_has_work;

View File

@ -44,7 +44,7 @@ typedef struct M68kCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} M68kCPUClass; } M68kCPUClass;
typedef struct M68kCPU M68kCPU; typedef struct M68kCPU M68kCPU;

View File

@ -41,16 +41,16 @@ static void m68k_set_feature(CPUM68KState *env, int feature)
env->features |= (1u << feature); env->features |= (1u << feature);
} }
/* CPUClass::reset() */ static void m68k_cpu_reset(DeviceState *dev)
static void m68k_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
M68kCPU *cpu = M68K_CPU(s); M68kCPU *cpu = M68K_CPU(s);
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
CPUM68KState *env = &cpu->env; CPUM68KState *env = &cpu->env;
floatx80 nan = floatx80_default_nan(NULL); floatx80 nan = floatx80_default_nan(NULL);
int i; int i;
mcc->parent_reset(s); mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUM68KState, end_reset_fields)); memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU
@ -273,7 +273,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, m68k_cpu_realizefn, device_class_set_parent_realize(dc, m68k_cpu_realizefn,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, m68k_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, m68k_cpu_reset, &mcc->parent_reset);
cc->class_by_name = m68k_cpu_class_by_name; cc->class_by_name = m68k_cpu_class_by_name;
cc->has_work = m68k_cpu_has_work; cc->has_work = m68k_cpu_has_work;

View File

@ -44,7 +44,7 @@ typedef struct MicroBlazeCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} MicroBlazeCPUClass; } MicroBlazeCPUClass;
typedef struct MicroBlazeCPU MicroBlazeCPU; typedef struct MicroBlazeCPU MicroBlazeCPU;

View File

@ -102,14 +102,14 @@ static void microblaze_cpu_set_irq(void *opaque, int irq, int level)
} }
#endif #endif
/* CPUClass::reset() */ static void mb_cpu_reset(DeviceState *dev)
static void mb_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
MicroBlazeCPU *cpu = MICROBLAZE_CPU(s); MicroBlazeCPU *cpu = MICROBLAZE_CPU(s);
MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu); MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu);
CPUMBState *env = &cpu->env; CPUMBState *env = &cpu->env;
mcc->parent_reset(s); mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMBState, end_reset_fields)); memset(env, 0, offsetof(CPUMBState, end_reset_fields));
env->res_addr = RES_ADDR_NONE; env->res_addr = RES_ADDR_NONE;
@ -292,7 +292,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, mb_cpu_realizefn, device_class_set_parent_realize(dc, mb_cpu_realizefn,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, mb_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, mb_cpu_reset, &mcc->parent_reset);
cc->class_by_name = mb_cpu_class_by_name; cc->class_by_name = mb_cpu_class_by_name;
cc->has_work = mb_cpu_has_work; cc->has_work = mb_cpu_has_work;

View File

@ -48,7 +48,7 @@ typedef struct MIPSCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
const struct mips_def_t *cpu_def; const struct mips_def_t *cpu_def;
} MIPSCPUClass; } MIPSCPUClass;

View File

@ -96,14 +96,14 @@ static bool mips_cpu_has_work(CPUState *cs)
return has_work; return has_work;
} }
/* CPUClass::reset() */ static void mips_cpu_reset(DeviceState *dev)
static void mips_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
MIPSCPU *cpu = MIPS_CPU(s); MIPSCPU *cpu = MIPS_CPU(s);
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
CPUMIPSState *env = &cpu->env; CPUMIPSState *env = &cpu->env;
mcc->parent_reset(s); mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields)); memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
@ -189,7 +189,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, mips_cpu_realizefn, device_class_set_parent_realize(dc, mips_cpu_realizefn,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, mips_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset);
cc->class_by_name = mips_cpu_class_by_name; cc->class_by_name = mips_cpu_class_by_name;
cc->has_work = mips_cpu_has_work; cc->has_work = mips_cpu_has_work;

View File

@ -35,13 +35,14 @@ static bool moxie_cpu_has_work(CPUState *cs)
return cs->interrupt_request & CPU_INTERRUPT_HARD; return cs->interrupt_request & CPU_INTERRUPT_HARD;
} }
static void moxie_cpu_reset(CPUState *s) static void moxie_cpu_reset(DeviceState *dev)
{ {
CPUState *s = CPU(dev);
MoxieCPU *cpu = MOXIE_CPU(s); MoxieCPU *cpu = MOXIE_CPU(s);
MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu); MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu);
CPUMoxieState *env = &cpu->env; CPUMoxieState *env = &cpu->env;
mcc->parent_reset(s); mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMoxieState, end_reset_fields)); memset(env, 0, offsetof(CPUMoxieState, end_reset_fields));
env->pc = 0x1000; env->pc = 0x1000;
@ -101,7 +102,7 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, moxie_cpu_realizefn, device_class_set_parent_realize(dc, moxie_cpu_realizefn,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, moxie_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, moxie_cpu_reset, &mcc->parent_reset);
cc->class_by_name = moxie_cpu_class_by_name; cc->class_by_name = moxie_cpu_class_by_name;

View File

@ -69,7 +69,7 @@ typedef struct MoxieCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} MoxieCPUClass; } MoxieCPUClass;
/** /**

View File

@ -39,9 +39,9 @@ static bool nios2_cpu_has_work(CPUState *cs)
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
} }
/* CPUClass::reset() */ static void nios2_cpu_reset(DeviceState *dev)
static void nios2_cpu_reset(CPUState *cs)
{ {
CPUState *cs = CPU(dev);
Nios2CPU *cpu = NIOS2_CPU(cs); Nios2CPU *cpu = NIOS2_CPU(cs);
Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu); Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu);
CPUNios2State *env = &cpu->env; CPUNios2State *env = &cpu->env;
@ -51,7 +51,7 @@ static void nios2_cpu_reset(CPUState *cs)
log_cpu_state(cs, 0); log_cpu_state(cs, 0);
} }
ncc->parent_reset(cs); ncc->parent_reset(dev);
memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS); memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS);
env->regs[R_PC] = cpu->reset_addr; env->regs[R_PC] = cpu->reset_addr;
@ -188,7 +188,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, nios2_cpu_realizefn, device_class_set_parent_realize(dc, nios2_cpu_realizefn,
&ncc->parent_realize); &ncc->parent_realize);
device_class_set_props(dc, nios2_properties); device_class_set_props(dc, nios2_properties);
cpu_class_set_parent_reset(cc, nios2_cpu_reset, &ncc->parent_reset); device_class_set_parent_reset(dc, nios2_cpu_reset, &ncc->parent_reset);
cc->class_by_name = nios2_cpu_class_by_name; cc->class_by_name = nios2_cpu_class_by_name;
cc->has_work = nios2_cpu_has_work; cc->has_work = nios2_cpu_has_work;

View File

@ -50,7 +50,7 @@ typedef struct Nios2CPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} Nios2CPUClass; } Nios2CPUClass;
#define TARGET_HAS_ICE 1 #define TARGET_HAS_ICE 1

View File

@ -41,13 +41,13 @@ static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
info->print_insn = print_insn_or1k; info->print_insn = print_insn_or1k;
} }
/* CPUClass::reset() */ static void openrisc_cpu_reset(DeviceState *dev)
static void openrisc_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
OpenRISCCPU *cpu = OPENRISC_CPU(s); OpenRISCCPU *cpu = OPENRISC_CPU(s);
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
occ->parent_reset(s); occ->parent_reset(dev);
memset(&cpu->env, 0, offsetof(CPUOpenRISCState, end_reset_fields)); memset(&cpu->env, 0, offsetof(CPUOpenRISCState, end_reset_fields));
@ -150,7 +150,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, openrisc_cpu_realizefn, device_class_set_parent_realize(dc, openrisc_cpu_realizefn,
&occ->parent_realize); &occ->parent_realize);
cpu_class_set_parent_reset(cc, openrisc_cpu_reset, &occ->parent_reset); device_class_set_parent_reset(dc, openrisc_cpu_reset, &occ->parent_reset);
cc->class_by_name = openrisc_cpu_class_by_name; cc->class_by_name = openrisc_cpu_class_by_name;
cc->has_work = openrisc_cpu_has_work; cc->has_work = openrisc_cpu_has_work;

View File

@ -48,7 +48,7 @@ typedef struct OpenRISCCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} OpenRISCCPUClass; } OpenRISCCPUClass;
#define TARGET_INSN_START_EXTRA_WORDS 1 #define TARGET_INSN_START_EXTRA_WORDS 1

View File

@ -166,7 +166,7 @@ typedef struct PowerPCCPUClass {
DeviceRealize parent_realize; DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize; DeviceUnrealize parent_unrealize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
void (*parent_parse_features)(const char *type, char *str, Error **errp); void (*parent_parse_features)(const char *type, char *str, Error **errp);
uint32_t pvr; uint32_t pvr;

View File

@ -10663,16 +10663,16 @@ static bool ppc_cpu_has_work(CPUState *cs)
return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
} }
/* CPUClass::reset() */ static void ppc_cpu_reset(DeviceState *dev)
static void ppc_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
PowerPCCPU *cpu = POWERPC_CPU(s); PowerPCCPU *cpu = POWERPC_CPU(s);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong msr; target_ulong msr;
int i; int i;
pcc->parent_reset(s); pcc->parent_reset(dev);
msr = (target_ulong)0; msr = (target_ulong)0;
msr |= (target_ulong)MSR_HVB; msr |= (target_ulong)MSR_HVB;
@ -10879,7 +10879,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always; pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
device_class_set_props(dc, ppc_cpu_properties); device_class_set_props(dc, ppc_cpu_properties);
cpu_class_set_parent_reset(cc, ppc_cpu_reset, &pcc->parent_reset); device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset);
cc->class_by_name = ppc_cpu_class_by_name; cc->class_by_name = ppc_cpu_class_by_name;
pcc->parent_parse_features = cc->parse_features; pcc->parent_parse_features = cc->parse_features;

View File

@ -330,13 +330,14 @@ void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
env->pc = data[0]; env->pc = data[0];
} }
static void riscv_cpu_reset(CPUState *cs) static void riscv_cpu_reset(DeviceState *dev)
{ {
CPUState *cs = CPU(dev);
RISCVCPU *cpu = RISCV_CPU(cs); RISCVCPU *cpu = RISCV_CPU(cs);
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
CPURISCVState *env = &cpu->env; CPURISCVState *env = &cpu->env;
mcc->parent_reset(cs); mcc->parent_reset(dev);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
env->priv = PRV_M; env->priv = PRV_M;
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV); env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
@ -511,7 +512,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, riscv_cpu_realize, device_class_set_parent_realize(dc, riscv_cpu_realize,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, riscv_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, riscv_cpu_reset, &mcc->parent_reset);
cc->class_by_name = riscv_cpu_class_by_name; cc->class_by_name = riscv_cpu_class_by_name;
cc->has_work = riscv_cpu_has_work; cc->has_work = riscv_cpu_has_work;

View File

@ -234,7 +234,7 @@ typedef struct RISCVCPUClass {
CPUClass parent_class; CPUClass parent_class;
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} RISCVCPUClass; } RISCVCPUClass;
/** /**

View File

@ -61,7 +61,7 @@ typedef struct S390CPUClass {
const char *desc; const char *desc;
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
void (*load_normal)(CPUState *cpu); void (*load_normal)(CPUState *cpu);
void (*reset)(CPUState *cpu, cpu_reset_type type); void (*reset)(CPUState *cpu, cpu_reset_type type);
} S390CPUClass; } S390CPUClass;

View File

@ -96,8 +96,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
S390CPU *cpu = S390_CPU(s); S390CPU *cpu = S390_CPU(s);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env; CPUS390XState *env = &cpu->env;
DeviceState *dev = DEVICE(s);
scc->parent_reset(s); scc->parent_reset(dev);
cpu->env.sigp_order = 0; cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
@ -450,8 +451,9 @@ static Property s390x_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST() DEFINE_PROP_END_OF_LIST()
}; };
static void s390_cpu_reset_full(CPUState *s) static void s390_cpu_reset_full(DeviceState *dev)
{ {
CPUState *s = CPU(dev);
return s390_cpu_reset(s, S390_CPU_RESET_CLEAR); return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
} }
@ -466,7 +468,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_props(dc, s390x_cpu_properties); device_class_set_props(dc, s390x_cpu_properties);
dc->user_creatable = true; dc->user_creatable = true;
cpu_class_set_parent_reset(cc, s390_cpu_reset_full, &scc->parent_reset); device_class_set_parent_reset(dc, s390_cpu_reset_full, &scc->parent_reset);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
scc->load_normal = s390_cpu_load_normal; scc->load_normal = s390_cpu_load_normal;
#endif #endif

View File

@ -51,7 +51,7 @@ typedef struct SuperHCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
uint32_t pvr; uint32_t pvr;
uint32_t prr; uint32_t prr;

View File

@ -47,14 +47,14 @@ static bool superh_cpu_has_work(CPUState *cs)
return cs->interrupt_request & CPU_INTERRUPT_HARD; return cs->interrupt_request & CPU_INTERRUPT_HARD;
} }
/* CPUClass::reset() */ static void superh_cpu_reset(DeviceState *dev)
static void superh_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
SuperHCPU *cpu = SUPERH_CPU(s); SuperHCPU *cpu = SUPERH_CPU(s);
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu); SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
CPUSH4State *env = &cpu->env; CPUSH4State *env = &cpu->env;
scc->parent_reset(s); scc->parent_reset(dev);
memset(env, 0, offsetof(CPUSH4State, end_reset_fields)); memset(env, 0, offsetof(CPUSH4State, end_reset_fields));
@ -214,7 +214,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, superh_cpu_realizefn, device_class_set_parent_realize(dc, superh_cpu_realizefn,
&scc->parent_realize); &scc->parent_realize);
cpu_class_set_parent_reset(cc, superh_cpu_reset, &scc->parent_reset); device_class_set_parent_reset(dc, superh_cpu_reset, &scc->parent_reset);
cc->class_by_name = superh_cpu_class_by_name; cc->class_by_name = superh_cpu_class_by_name;
cc->has_work = superh_cpu_has_work; cc->has_work = superh_cpu_has_work;

View File

@ -49,7 +49,7 @@ typedef struct SPARCCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
sparc_def_t *cpu_def; sparc_def_t *cpu_def;
} SPARCCPUClass; } SPARCCPUClass;

View File

@ -28,14 +28,14 @@
//#define DEBUG_FEATURES //#define DEBUG_FEATURES
/* CPUClass::reset() */ static void sparc_cpu_reset(DeviceState *dev)
static void sparc_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
SPARCCPU *cpu = SPARC_CPU(s); SPARCCPU *cpu = SPARC_CPU(s);
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu); SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
CPUSPARCState *env = &cpu->env; CPUSPARCState *env = &cpu->env;
scc->parent_reset(s); scc->parent_reset(dev);
memset(env, 0, offsetof(CPUSPARCState, end_reset_fields)); memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
env->cwp = 0; env->cwp = 0;
@ -859,7 +859,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
&scc->parent_realize); &scc->parent_realize);
device_class_set_props(dc, sparc_cpu_properties); device_class_set_props(dc, sparc_cpu_properties);
cpu_class_set_parent_reset(cc, sparc_cpu_reset, &scc->parent_reset); device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset);
cc->class_by_name = sparc_cpu_class_by_name; cc->class_by_name = sparc_cpu_class_by_name;
cc->parse_features = sparc_cpu_parse_features; cc->parse_features = sparc_cpu_parse_features;

View File

@ -68,13 +68,14 @@ static bool tilegx_cpu_has_work(CPUState *cs)
return true; return true;
} }
static void tilegx_cpu_reset(CPUState *s) static void tilegx_cpu_reset(DeviceState *dev)
{ {
CPUState *s = CPU(dev);
TileGXCPU *cpu = TILEGX_CPU(s); TileGXCPU *cpu = TILEGX_CPU(s);
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(cpu); TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(cpu);
CPUTLGState *env = &cpu->env; CPUTLGState *env = &cpu->env;
tcc->parent_reset(s); tcc->parent_reset(dev);
memset(env, 0, offsetof(CPUTLGState, end_reset_fields)); memset(env, 0, offsetof(CPUTLGState, end_reset_fields));
} }
@ -142,7 +143,7 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, tilegx_cpu_realizefn, device_class_set_parent_realize(dc, tilegx_cpu_realizefn,
&tcc->parent_realize); &tcc->parent_realize);
cpu_class_set_parent_reset(cc, tilegx_cpu_reset, &tcc->parent_reset); device_class_set_parent_reset(dc, tilegx_cpu_reset, &tcc->parent_reset);
cc->class_by_name = tilegx_cpu_class_by_name; cc->class_by_name = tilegx_cpu_class_by_name;
cc->has_work = tilegx_cpu_has_work; cc->has_work = tilegx_cpu_has_work;

View File

@ -118,7 +118,7 @@ typedef struct TileGXCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} TileGXCPUClass; } TileGXCPUClass;
/** /**

View File

@ -36,7 +36,7 @@ typedef struct TriCoreCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
} TriCoreCPUClass; } TriCoreCPUClass;
typedef struct TriCoreCPU TriCoreCPU; typedef struct TriCoreCPU TriCoreCPU;

View File

@ -53,13 +53,14 @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs,
env->PC = tb->pc; env->PC = tb->pc;
} }
static void tricore_cpu_reset(CPUState *s) static void tricore_cpu_reset(DeviceState *dev)
{ {
CPUState *s = CPU(dev);
TriCoreCPU *cpu = TRICORE_CPU(s); TriCoreCPU *cpu = TRICORE_CPU(s);
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu); TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
CPUTriCoreState *env = &cpu->env; CPUTriCoreState *env = &cpu->env;
tcc->parent_reset(s); tcc->parent_reset(dev);
cpu_state_reset(env); cpu_state_reset(env);
} }
@ -153,7 +154,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, tricore_cpu_realizefn, device_class_set_parent_realize(dc, tricore_cpu_realizefn,
&mcc->parent_realize); &mcc->parent_realize);
cpu_class_set_parent_reset(cc, tricore_cpu_reset, &mcc->parent_reset); device_class_set_parent_reset(dc, tricore_cpu_reset, &mcc->parent_reset);
cc->class_by_name = tricore_cpu_class_by_name; cc->class_by_name = tricore_cpu_class_by_name;
cc->has_work = tricore_cpu_has_work; cc->has_work = tricore_cpu_has_work;

View File

@ -56,7 +56,7 @@ typedef struct XtensaCPUClass {
/*< public >*/ /*< public >*/
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); DeviceReset parent_reset;
const XtensaConfig *config; const XtensaConfig *config;
} XtensaCPUClass; } XtensaCPUClass;

View File

@ -67,14 +67,14 @@ bool xtensa_abi_call0(void)
} }
#endif #endif
/* CPUClass::reset() */ static void xtensa_cpu_reset(DeviceState *dev)
static void xtensa_cpu_reset(CPUState *s)
{ {
CPUState *s = CPU(dev);
XtensaCPU *cpu = XTENSA_CPU(s); XtensaCPU *cpu = XTENSA_CPU(s);
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu); XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu);
CPUXtensaState *env = &cpu->env; CPUXtensaState *env = &cpu->env;
xcc->parent_reset(s); xcc->parent_reset(dev);
env->exception_taken = 0; env->exception_taken = 0;
env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors]; env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors];
@ -184,7 +184,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, xtensa_cpu_realizefn, device_class_set_parent_realize(dc, xtensa_cpu_realizefn,
&xcc->parent_realize); &xcc->parent_realize);
cpu_class_set_parent_reset(cc, xtensa_cpu_reset, &xcc->parent_reset); device_class_set_parent_reset(dc, xtensa_cpu_reset, &xcc->parent_reset);
cc->class_by_name = xtensa_cpu_class_by_name; cc->class_by_name = xtensa_cpu_class_by_name;
cc->has_work = xtensa_cpu_has_work; cc->has_work = xtensa_cpu_has_work;

View File

@ -28,79 +28,101 @@
static void test_topo_bits(void) static void test_topo_bits(void)
{ {
/* simple tests for 1 thread per core, 1 core per die, 1 die per package */ X86CPUTopoInfo topo_info = {0};
g_assert_cmpuint(apicid_smt_width(1, 1, 1), ==, 0);
g_assert_cmpuint(apicid_core_width(1, 1, 1), ==, 0);
g_assert_cmpuint(apicid_die_width(1, 1, 1), ==, 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 0), ==, 0); /* simple tests for 1 thread per core, 1 core per die, 1 die per package */
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 1), ==, 1); topo_info = (X86CPUTopoInfo) {0, 1, 1, 1};
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 2), ==, 2); g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 3), ==, 3); g_assert_cmpuint(apicid_core_width(&topo_info), ==, 0);
g_assert_cmpuint(apicid_die_width(&topo_info), ==, 0);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 1};
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 0), ==, 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1), ==, 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2), ==, 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 3), ==, 3);
/* Test field width calculation for multiple values /* Test field width calculation for multiple values
*/ */
g_assert_cmpuint(apicid_smt_width(1, 1, 2), ==, 1); topo_info = (X86CPUTopoInfo) {0, 1, 1, 2};
g_assert_cmpuint(apicid_smt_width(1, 1, 3), ==, 2); g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 1);
g_assert_cmpuint(apicid_smt_width(1, 1, 4), ==, 2); topo_info = (X86CPUTopoInfo) {0, 1, 1, 3};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 4};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2);
g_assert_cmpuint(apicid_smt_width(1, 1, 14), ==, 4); topo_info = (X86CPUTopoInfo) {0, 1, 1, 14};
g_assert_cmpuint(apicid_smt_width(1, 1, 15), ==, 4); g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4);
g_assert_cmpuint(apicid_smt_width(1, 1, 16), ==, 4); topo_info = (X86CPUTopoInfo) {0, 1, 1, 15};
g_assert_cmpuint(apicid_smt_width(1, 1, 17), ==, 5); g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 16};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 17};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 5);
g_assert_cmpuint(apicid_core_width(1, 30, 2), ==, 5); topo_info = (X86CPUTopoInfo) {0, 1, 30, 2};
g_assert_cmpuint(apicid_core_width(1, 31, 2), ==, 5); g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5);
g_assert_cmpuint(apicid_core_width(1, 32, 2), ==, 5); topo_info = (X86CPUTopoInfo) {0, 1, 31, 2};
g_assert_cmpuint(apicid_core_width(1, 33, 2), ==, 6); g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5);
topo_info = (X86CPUTopoInfo) {0, 1, 32, 2};
g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5);
topo_info = (X86CPUTopoInfo) {0, 1, 33, 2};
g_assert_cmpuint(apicid_core_width(&topo_info), ==, 6);
g_assert_cmpuint(apicid_die_width(1, 30, 2), ==, 0); topo_info = (X86CPUTopoInfo) {0, 1, 30, 2};
g_assert_cmpuint(apicid_die_width(2, 30, 2), ==, 1); g_assert_cmpuint(apicid_die_width(&topo_info), ==, 0);
g_assert_cmpuint(apicid_die_width(3, 30, 2), ==, 2); topo_info = (X86CPUTopoInfo) {0, 2, 30, 2};
g_assert_cmpuint(apicid_die_width(4, 30, 2), ==, 2); g_assert_cmpuint(apicid_die_width(&topo_info), ==, 1);
topo_info = (X86CPUTopoInfo) {0, 3, 30, 2};
g_assert_cmpuint(apicid_die_width(&topo_info), ==, 2);
topo_info = (X86CPUTopoInfo) {0, 4, 30, 2};
g_assert_cmpuint(apicid_die_width(&topo_info), ==, 2);
/* build a weird topology and see if IDs are calculated correctly /* build a weird topology and see if IDs are calculated correctly
*/ */
/* This will use 2 bits for thread ID and 3 bits for core ID /* This will use 2 bits for thread ID and 3 bits for core ID
*/ */
g_assert_cmpuint(apicid_smt_width(1, 6, 3), ==, 2); topo_info = (X86CPUTopoInfo) {0, 1, 6, 3};
g_assert_cmpuint(apicid_core_offset(1, 6, 3), ==, 2); g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2);
g_assert_cmpuint(apicid_die_offset(1, 6, 3), ==, 5); g_assert_cmpuint(apicid_core_offset(&topo_info), ==, 2);
g_assert_cmpuint(apicid_pkg_offset(1, 6, 3), ==, 5); g_assert_cmpuint(apicid_die_offset(&topo_info), ==, 5);
g_assert_cmpuint(apicid_pkg_offset(&topo_info), ==, 5);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 0), ==, 0); topo_info = (X86CPUTopoInfo) {0, 1, 6, 3};
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1), ==, 1); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 0), ==, 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2), ==, 2); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1), ==, 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2), ==, 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 0), ==, topo_info = (X86CPUTopoInfo) {0, 1, 6, 3};
g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1 * 3 + 0), ==,
(1 << 2) | 0); (1 << 2) | 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 1), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1 * 3 + 1), ==,
(1 << 2) | 1); (1 << 2) | 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 2), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1 * 3 + 2), ==,
(1 << 2) | 2); (1 << 2) | 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 0), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2 * 3 + 0), ==,
(2 << 2) | 0); (2 << 2) | 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 1), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2 * 3 + 1), ==,
(2 << 2) | 1); (2 << 2) | 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 2), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2 * 3 + 2), ==,
(2 << 2) | 2); (2 << 2) | 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 0), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 5 * 3 + 0), ==,
(5 << 2) | 0); (5 << 2) | 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 1), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 5 * 3 + 1), ==,
(5 << 2) | 1); (5 << 2) | 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 2), ==, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 5 * 3 + 2), ==,
(5 << 2) | 2); (5 << 2) | 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info,
1 * 6 * 3 + 0 * 3 + 0), ==, (1 << 5)); 1 * 6 * 3 + 0 * 3 + 0), ==, (1 << 5));
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info,
1 * 6 * 3 + 1 * 3 + 1), ==, (1 << 5) | (1 << 2) | 1); 1 * 6 * 3 + 1 * 3 + 1), ==, (1 << 5) | (1 << 2) | 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info,
3 * 6 * 3 + 5 * 3 + 2), ==, (3 << 5) | (5 << 2) | 2); 3 * 6 * 3 + 5 * 3 + 2), ==, (3 << 5) | (5 << 2) | 2);
} }