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)
{
CPUClass *klass = CPU_GET_CLASS(cpu);
if (klass->reset != NULL) {
(*klass->reset)(cpu);
}
device_cold_reset(DEVICE(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);
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);
k->parse_features = cpu_common_parse_features;
k->reset = cpu_common_reset;
k->get_arch_id = cpu_common_get_arch_id;
k->has_work = cpu_common_has_work;
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);
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
dc->reset = cpu_common_reset;
device_class_set_props(dc, cpu_common_props);
/*
* 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);
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)
@ -749,6 +757,7 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
ms->smp.cpus = cpus;
ms->smp.cores = cores;
ms->smp.threads = threads;
ms->smp.sockets = sockets;
}
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.cores = cores;
ms->smp.threads = threads;
ms->smp.sockets = sockets;
x86ms->smp_dies = dies;
}
@ -1505,7 +1506,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
int idx;
CPUState *cs;
CPUArchId *cpu_slot;
X86CPUTopoInfo topo;
X86CPUTopoIDs topo_ids;
X86CPU *cpu = X86_CPU(dev);
CPUX86State *env = &cpu->env;
MachineState *ms = MACHINE(hotplug_dev);
@ -1513,6 +1514,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
X86MachineState *x86ms = X86_MACHINE(pcms);
unsigned int smp_cores = ms->smp.cores;
unsigned int smp_threads = ms->smp.threads;
X86CPUTopoInfo topo_info;
if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
@ -1520,7 +1522,10 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return;
}
init_topo_info(&topo_info, x86ms);
env->nr_dies = x86ms->smp_dies;
env->nr_nodes = topo_info.nodes_per_pkg;
/*
* If APIC ID is not set,
@ -1571,24 +1576,22 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return;
}
topo.pkg_id = cpu->socket_id;
topo.die_id = cpu->die_id;
topo.core_id = cpu->core_id;
topo.smt_id = cpu->thread_id;
cpu->apic_id = apicid_from_topo_ids(x86ms->smp_dies, smp_cores,
smp_threads, &topo);
topo_ids.pkg_id = cpu->socket_id;
topo_ids.die_id = cpu->die_id;
topo_ids.core_id = cpu->core_id;
topo_ids.smt_id = cpu->thread_id;
cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids);
}
cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx);
if (!cpu_slot) {
MachineState *ms = MACHINE(pcms);
x86_topo_ids_from_apicid(cpu->apic_id, x86ms->smp_dies,
smp_cores, smp_threads, &topo);
x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
error_setg(errp,
"Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
" 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);
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()
* once -smp refactoring is complete and there will be CPU private
* CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
x86_topo_ids_from_apicid(cpu->apic_id, x86ms->smp_dies,
smp_cores, smp_threads, &topo);
if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_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;
}
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:"
" 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;
}
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:"
" 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;
}
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:"
" 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;
}
cpu->thread_id = topo.smt_id;
cpu->thread_id = topo_ids.smt_id;
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
!kvm_hv_vpindex_settable()) {

View File

@ -57,6 +57,17 @@
/* Physical Address of PVH entry point read from kernel ELF NOTE */
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
*
@ -68,13 +79,14 @@ static size_t pvh_start_addr;
uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
unsigned int cpu_index)
{
MachineState *ms = MACHINE(x86ms);
X86MachineClass *x86mc = X86_MACHINE_GET_CLASS(x86ms);
X86CPUTopoInfo topo_info;
uint32_t correct_id;
static bool warned;
correct_id = x86_apicid_from_cpu_idx(x86ms->smp_dies, ms->smp.cores,
ms->smp.threads, cpu_index);
init_topo_info(&topo_info, x86ms);
correct_id = x86_apicid_from_cpu_idx(&topo_info, cpu_index);
if (x86mc->compat_apic_id_mode) {
if (cpu_index != correct_id && !warned && !qtest_enabled()) {
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;
Error *local_err = NULL;
CPUX86State *env = NULL;
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_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)
{
X86CPUTopoInfo topo;
X86CPUTopoIDs topo_ids;
X86MachineState *x86ms = X86_MACHINE(ms);
X86CPUTopoInfo topo_info;
init_topo_info(&topo_info, x86ms);
assert(idx < ms->possible_cpus->len);
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
x86ms->smp_dies, ms->smp.cores,
ms->smp.threads, &topo);
return topo.pkg_id % ms->numa_state->num_nodes;
&topo_info, &topo_ids);
return topo_ids.pkg_id % ms->numa_state->num_nodes;
}
const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
{
X86MachineState *x86ms = X86_MACHINE(ms);
int i;
unsigned int max_cpus = ms->smp.max_cpus;
X86CPUTopoInfo topo_info;
int i;
if (ms->possible_cpus) {
/*
@ -171,26 +182,28 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
sizeof(CPUArchId) * max_cpus);
ms->possible_cpus->len = max_cpus;
init_topo_info(&topo_info, x86ms);
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].vcpus_count = 1;
ms->possible_cpus->cpus[i].arch_id =
x86_cpu_apic_id_from_index(x86ms, i);
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
x86ms->smp_dies, ms->smp.cores,
ms->smp.threads, &topo);
&topo_info, &topo_ids);
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) {
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.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.thread_id = topo.smt_id;
ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id;
}
return ms->possible_cpus;
}

View File

@ -236,12 +236,14 @@ typedef struct DeviceMemoryState {
* @cpus: the number of present logical processors on the machine
* @cores: the number of cores in one package
* @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
*/
typedef struct CpuTopology {
unsigned int cpus;
unsigned int cores;
unsigned int threads;
unsigned int sockets;
unsigned int max_cpus;
} CpuTopology;

View File

@ -79,7 +79,6 @@ struct TranslationBlock;
* @class_by_name: Callback to map -cpu command line model name to an
* instantiatable CPU type.
* @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.
* @has_work: Callback for checking if there is work to do.
* @do_interrupt: Callback for interrupt handling.
@ -165,7 +164,6 @@ typedef struct CPUClass {
ObjectClass *(*class_by_name)(const char *cpu_model);
void (*parse_features)(const char *typename, char *str, Error **errp);
void (*reset)(CPUState *cpu);
int reset_dump_flags;
bool (*has_work)(CPUState *cpu);
void (*do_interrupt)(CPUState *cpu);
@ -1135,10 +1133,6 @@ void cpu_exec_unrealizefn(CPUState *cpu);
*/
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 CONFIG_SOFTMMU

View File

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

View File

@ -21,6 +21,7 @@
#include "exec/hwaddr.h"
#include "qemu/notify.h"
#include "hw/i386/topology.h"
#include "hw/boards.h"
#include "hw/nmi.h"
#include "hw/isa/isa.h"
@ -82,6 +83,8 @@ typedef struct {
#define X86_MACHINE_CLASS(class) \
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,
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.cores = 1;
current_machine->smp.threads = 1;
current_machine->smp.sockets = 1;
machine_class->smp_parse(current_machine,
qemu_opts_find(qemu_find_opts("smp-opts"), NULL));

View File

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

View File

@ -51,7 +51,7 @@ typedef struct ARMCPUClass {
const ARMCPUInfo *info;
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
} ARMCPUClass;
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);
}
/* CPUClass::reset() */
static void arm_cpu_reset(CPUState *s)
static void arm_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
ARMCPU *cpu = ARM_CPU(s);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
CPUARMState *env = &cpu->env;
acc->parent_reset(s);
acc->parent_reset(dev);
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);
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->has_work = arm_cpu_has_work;

View File

@ -45,7 +45,7 @@ typedef struct CRISCPUClass {
/*< public >*/
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
uint32_t vr;
} 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);
}
/* CPUClass::reset() */
static void cris_cpu_reset(CPUState *s)
static void cris_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
CRISCPU *cpu = CRIS_CPU(s);
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(cpu);
CPUCRISState *env = &cpu->env;
uint32_t vr;
ccc->parent_reset(s);
ccc->parent_reset(dev);
vr = env->pregs[PR_VR];
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,
&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->has_work = cris_cpu_has_work;

View File

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

View File

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

View File

@ -1133,7 +1133,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"clzero", NULL, "xsaveerptr", NULL,
NULL, NULL, NULL, NULL,
NULL, "wbnoinvd", NULL, NULL,
"ibpb", NULL, NULL, NULL,
"ibpb", NULL, NULL, "amd-stibp",
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
"amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL,
@ -1690,6 +1690,7 @@ typedef struct PropValue {
typedef struct X86CPUVersionDefinition {
X86CPUVersion version;
const char *alias;
const char *note;
PropValue *props;
} X86CPUVersionDefinition;
@ -1720,6 +1721,7 @@ struct X86CPUModel {
X86CPUDefinition *cpudef;
/* CPU model version */
X86CPUVersion version;
const char *note;
/*
* If true, this is an alias CPU model.
* 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
* CPU definitions:
*
@ -3592,6 +3644,18 @@ static X86CPUDefinition builtin_x86_defs[] = {
.features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING,
.xlevel = 0x80000008,
.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",
@ -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_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT |
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] =
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
CPUID_XSAVE_XGETBV1,
@ -3954,6 +4014,19 @@ static X86CPUDefinition builtin_x86_defs[] = {
{ /* 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 */ }
}
},
@ -4007,6 +4080,56 @@ static X86CPUDefinition builtin_x86_defs[] = {
.model_id = "Hygon Dhyana Processor",
.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
@ -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 *desc = g_strdup(cc->model_description);
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 (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);
}
}
if (!desc && cc->model && cc->model->note) {
desc = g_strdup_printf("%s [%s]", model_id, cc->model->note);
}
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 */
@ -5338,6 +5465,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
x86_cpu_versioned_model_name(def, vdef->version);
m->cpudef = def;
m->version = vdef->version;
m->note = vdef->note;
x86_register_cpu_model_type(name, m);
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 limit;
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 */
if (index >= 0xC0000000) {
@ -5455,8 +5588,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
eax, ebx, ecx, edx);
break;
case 3: /* L3 cache info */
die_offset = apicid_die_offset(env->nr_dies,
cs->nr_cores, cs->nr_threads);
die_offset = apicid_die_offset(&topo_info);
if (cpu->enable_l3_cache) {
encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache,
(1 << die_offset), cs->nr_cores,
@ -5547,14 +5679,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch (count) {
case 0:
*eax = apicid_core_offset(env->nr_dies,
cs->nr_cores, cs->nr_threads);
*eax = apicid_core_offset(&topo_info);
*ebx = cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
break;
case 1:
*eax = apicid_pkg_offset(env->nr_dies,
cs->nr_cores, cs->nr_threads);
*eax = apicid_pkg_offset(&topo_info);
*ebx = cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
break;
@ -5578,20 +5708,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = cpu->apic_id;
switch (count) {
case 0:
*eax = apicid_core_offset(env->nr_dies, cs->nr_cores,
cs->nr_threads);
*eax = apicid_core_offset(&topo_info);
*ebx = cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
break;
case 1:
*eax = apicid_die_offset(env->nr_dies, cs->nr_cores,
cs->nr_threads);
*eax = apicid_die_offset(&topo_info);
*ebx = cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
break;
case 2:
*eax = apicid_pkg_offset(env->nr_dies, cs->nr_cores,
cs->nr_threads);
*eax = apicid_pkg_offset(&topo_info);
*ebx = env->nr_dies * cs->nr_cores * cs->nr_threads;
*ecx |= CPUID_TOPOLOGY_LEVEL_DIE;
break;
@ -5855,9 +5982,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
}
/* CPUClass::reset() */
static void x86_cpu_reset(CPUState *s)
static void x86_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
X86CPU *cpu = X86_CPU(s);
X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
CPUX86State *env = &cpu->env;
@ -5865,7 +5992,7 @@ static void x86_cpu_reset(CPUState *s)
uint64_t xcr0;
int i;
xcc->parent_reset(s);
xcc->parent_reset(dev);
memset(env, 0, offsetof(CPUX86State, end_reset_fields));
@ -6830,6 +6957,7 @@ static void x86_cpu_initfn(Object *obj)
FeatureWord w;
env->nr_dies = 1;
env->nr_nodes = 1;
cpu_set_cpustate_pointers(cpu);
object_property_add(obj, "family", "int",
@ -7169,7 +7297,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
&xcc->parent_unrealize);
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->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)
/* Indirect Branch Prediction Barrier */
#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_XSAVEC (1U << 1)
@ -1607,6 +1609,7 @@ typedef struct CPUX86State {
TPRAccess tpr_access_type;
unsigned nr_dies;
unsigned nr_nodes;
} CPUX86State;
struct kvm_msrs;

View File

@ -44,7 +44,7 @@ typedef struct LM32CPUClass {
/*< public >*/
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
} LM32CPUClass;
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;
}
/* CPUClass::reset() */
static void lm32_cpu_reset(CPUState *s)
static void lm32_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
LM32CPU *cpu = LM32_CPU(s);
LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
CPULM32State *env = &cpu->env;
lcc->parent_reset(s);
lcc->parent_reset(dev);
/* reset cpu state */
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,
&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->has_work = lm32_cpu_has_work;

View File

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

View File

@ -41,16 +41,16 @@ static void m68k_set_feature(CPUM68KState *env, int feature)
env->features |= (1u << feature);
}
/* CPUClass::reset() */
static void m68k_cpu_reset(CPUState *s)
static void m68k_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
M68kCPU *cpu = M68K_CPU(s);
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
CPUM68KState *env = &cpu->env;
floatx80 nan = floatx80_default_nan(NULL);
int i;
mcc->parent_reset(s);
mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
#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,
&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->has_work = m68k_cpu_has_work;

View File

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

View File

@ -102,14 +102,14 @@ static void microblaze_cpu_set_irq(void *opaque, int irq, int level)
}
#endif
/* CPUClass::reset() */
static void mb_cpu_reset(CPUState *s)
static void mb_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
MicroBlazeCPU *cpu = MICROBLAZE_CPU(s);
MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu);
CPUMBState *env = &cpu->env;
mcc->parent_reset(s);
mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMBState, end_reset_fields));
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,
&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->has_work = mb_cpu_has_work;

View File

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

View File

@ -96,14 +96,14 @@ static bool mips_cpu_has_work(CPUState *cs)
return has_work;
}
/* CPUClass::reset() */
static void mips_cpu_reset(CPUState *s)
static void mips_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
MIPSCPU *cpu = MIPS_CPU(s);
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
CPUMIPSState *env = &cpu->env;
mcc->parent_reset(s);
mcc->parent_reset(dev);
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,
&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->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;
}
static void moxie_cpu_reset(CPUState *s)
static void moxie_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
MoxieCPU *cpu = MOXIE_CPU(s);
MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu);
CPUMoxieState *env = &cpu->env;
mcc->parent_reset(s);
mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMoxieState, end_reset_fields));
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,
&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;

View File

@ -69,7 +69,7 @@ typedef struct MoxieCPUClass {
/*< public >*/
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
} 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);
}
/* CPUClass::reset() */
static void nios2_cpu_reset(CPUState *cs)
static void nios2_cpu_reset(DeviceState *dev)
{
CPUState *cs = CPU(dev);
Nios2CPU *cpu = NIOS2_CPU(cs);
Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu);
CPUNios2State *env = &cpu->env;
@ -51,7 +51,7 @@ static void nios2_cpu_reset(CPUState *cs)
log_cpu_state(cs, 0);
}
ncc->parent_reset(cs);
ncc->parent_reset(dev);
memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS);
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,
&ncc->parent_realize);
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->has_work = nios2_cpu_has_work;

View File

@ -50,7 +50,7 @@ typedef struct Nios2CPUClass {
/*< public >*/
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
} Nios2CPUClass;
#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;
}
/* CPUClass::reset() */
static void openrisc_cpu_reset(CPUState *s)
static void openrisc_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
OpenRISCCPU *cpu = OPENRISC_CPU(s);
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
occ->parent_reset(s);
occ->parent_reset(dev);
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,
&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->has_work = openrisc_cpu_has_work;

View File

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

View File

@ -166,7 +166,7 @@ typedef struct PowerPCCPUClass {
DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize;
void (*parent_reset)(CPUState *cpu);
DeviceReset parent_reset;
void (*parent_parse_features)(const char *type, char *str, Error **errp);
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);
}
/* CPUClass::reset() */
static void ppc_cpu_reset(CPUState *s)
static void ppc_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
PowerPCCPU *cpu = POWERPC_CPU(s);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr;
int i;
pcc->parent_reset(s);
pcc->parent_reset(dev);
msr = (target_ulong)0;
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;
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;
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];
}
static void riscv_cpu_reset(CPUState *cs)
static void riscv_cpu_reset(DeviceState *dev)
{
CPUState *cs = CPU(dev);
RISCVCPU *cpu = RISCV_CPU(cs);
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
CPURISCVState *env = &cpu->env;
mcc->parent_reset(cs);
mcc->parent_reset(dev);
#ifndef CONFIG_USER_ONLY
env->priv = PRV_M;
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,
&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->has_work = riscv_cpu_has_work;

View File

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

View File

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

View File

@ -96,8 +96,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
S390CPU *cpu = S390_CPU(s);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env;
DeviceState *dev = DEVICE(s);
scc->parent_reset(s);
scc->parent_reset(dev);
cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
@ -450,8 +451,9 @@ static Property s390x_cpu_properties[] = {
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);
}
@ -466,7 +468,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_props(dc, s390x_cpu_properties);
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)
scc->load_normal = s390_cpu_load_normal;
#endif

View File

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

View File

@ -47,14 +47,14 @@ static bool superh_cpu_has_work(CPUState *cs)
return cs->interrupt_request & CPU_INTERRUPT_HARD;
}
/* CPUClass::reset() */
static void superh_cpu_reset(CPUState *s)
static void superh_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
SuperHCPU *cpu = SUPERH_CPU(s);
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
CPUSH4State *env = &cpu->env;
scc->parent_reset(s);
scc->parent_reset(dev);
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,
&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->has_work = superh_cpu_has_work;

View File

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

View File

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

View File

@ -68,13 +68,14 @@ static bool tilegx_cpu_has_work(CPUState *cs)
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);
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(cpu);
CPUTLGState *env = &cpu->env;
tcc->parent_reset(s);
tcc->parent_reset(dev);
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,
&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->has_work = tilegx_cpu_has_work;

View File

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

View File

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

View File

@ -53,13 +53,14 @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs,
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);
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
CPUTriCoreState *env = &cpu->env;
tcc->parent_reset(s);
tcc->parent_reset(dev);
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,
&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->has_work = tricore_cpu_has_work;

View File

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

View File

@ -67,14 +67,14 @@ bool xtensa_abi_call0(void)
}
#endif
/* CPUClass::reset() */
static void xtensa_cpu_reset(CPUState *s)
static void xtensa_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
XtensaCPU *cpu = XTENSA_CPU(s);
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu);
CPUXtensaState *env = &cpu->env;
xcc->parent_reset(s);
xcc->parent_reset(dev);
env->exception_taken = 0;
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,
&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->has_work = xtensa_cpu_has_work;

View File

@ -28,79 +28,101 @@
static void test_topo_bits(void)
{
/* simple tests for 1 thread per core, 1 core per die, 1 die per package */
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);
X86CPUTopoInfo topo_info = {0};
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 0), ==, 0);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 1), ==, 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 2), ==, 2);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 3), ==, 3);
/* simple tests for 1 thread per core, 1 core per die, 1 die per package */
topo_info = (X86CPUTopoInfo) {0, 1, 1, 1};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 0);
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
*/
g_assert_cmpuint(apicid_smt_width(1, 1, 2), ==, 1);
g_assert_cmpuint(apicid_smt_width(1, 1, 3), ==, 2);
g_assert_cmpuint(apicid_smt_width(1, 1, 4), ==, 2);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 2};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 1);
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);
g_assert_cmpuint(apicid_smt_width(1, 1, 15), ==, 4);
g_assert_cmpuint(apicid_smt_width(1, 1, 16), ==, 4);
g_assert_cmpuint(apicid_smt_width(1, 1, 17), ==, 5);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 14};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4);
topo_info = (X86CPUTopoInfo) {0, 1, 1, 15};
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);
g_assert_cmpuint(apicid_core_width(1, 31, 2), ==, 5);
g_assert_cmpuint(apicid_core_width(1, 32, 2), ==, 5);
g_assert_cmpuint(apicid_core_width(1, 33, 2), ==, 6);
topo_info = (X86CPUTopoInfo) {0, 1, 30, 2};
g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5);
topo_info = (X86CPUTopoInfo) {0, 1, 31, 2};
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);
g_assert_cmpuint(apicid_die_width(2, 30, 2), ==, 1);
g_assert_cmpuint(apicid_die_width(3, 30, 2), ==, 2);
g_assert_cmpuint(apicid_die_width(4, 30, 2), ==, 2);
topo_info = (X86CPUTopoInfo) {0, 1, 30, 2};
g_assert_cmpuint(apicid_die_width(&topo_info), ==, 0);
topo_info = (X86CPUTopoInfo) {0, 2, 30, 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
*/
/* This will use 2 bits for thread ID and 3 bits for core ID
*/
g_assert_cmpuint(apicid_smt_width(1, 6, 3), ==, 2);
g_assert_cmpuint(apicid_core_offset(1, 6, 3), ==, 2);
g_assert_cmpuint(apicid_die_offset(1, 6, 3), ==, 5);
g_assert_cmpuint(apicid_pkg_offset(1, 6, 3), ==, 5);
topo_info = (X86CPUTopoInfo) {0, 1, 6, 3};
g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2);
g_assert_cmpuint(apicid_core_offset(&topo_info), ==, 2);
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);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1), ==, 1);
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2), ==, 2);
topo_info = (X86CPUTopoInfo) {0, 1, 6, 3};
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(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);
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);
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);
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);
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);
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);
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);
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);
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);
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));
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);
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);
}