@@ -223,6 +223,17 @@ static void cpu_common_unrealizefn(DeviceState *dev)
cpu_exec_unrealizefn(cpu);
}
+static void cpu_topo_init(CPUState *cpu)
+{
+ cpu->topo.sockets = 1;
+ cpu->topo.cores_per_socket = 1;
+ cpu->topo.threads_per_socket = 1;
+ cpu->topo.dies_per_socket = 1;
+ cpu->topo.clusters_per_die = 1;
+ cpu->topo.cores_per_cluster = 1;
+ cpu->topo.threads_per_core = 1;
+}
+
static void cpu_common_initfn(Object *obj)
{
CPUState *cpu = CPU(obj);
@@ -233,8 +244,7 @@ static void cpu_common_initfn(Object *obj)
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
/* *-user doesn't have configurable SMP topology */
/* the default value is changed by qemu_init_vcpu() for softmmu */
- cpu->nr_cores = 1;
- cpu->nr_threads = 1;
+ cpu_topo_init(cpu);
cpu->cflags_next_tb = -1;
qemu_mutex_init(&cpu->work_mutex);
@@ -409,12 +409,16 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
return;
}
- /* if 'address' properties socket-id/core-id/thread-id are not set, set them
+ /*
+ * if 'address' properties socket-id/core-id/thread-id are not set, set them
* so that machine_query_hotpluggable_cpus would show correct values
*/
- /* 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
- * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
+ * CPUState::topo::cores_per_socket and CPUState::topo::threads_per_core
+ * fields instead of globals
+ */
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:"
@@ -986,11 +986,13 @@ static void malta_mips_config(MIPSCPU *cpu)
CPUState *cs = CPU(cpu);
if (ase_mt_available(env)) {
- env->mvp->CP0_MVPConf0 = deposit32(env->mvp->CP0_MVPConf0,
- CP0MVPC0_PTC, 8,
- smp_cpus * cs->nr_threads - 1);
- env->mvp->CP0_MVPConf0 = deposit32(env->mvp->CP0_MVPConf0,
- CP0MVPC0_PVPE, 4, smp_cpus - 1);
+ env->mvp->CP0_MVPConf0 =
+ deposit32(env->mvp->CP0_MVPConf0,
+ CP0MVPC0_PTC, 8,
+ smp_cpus * cs->topo.threads_per_core - 1);
+ env->mvp->CP0_MVPConf0 =
+ deposit32(env->mvp->CP0_MVPConf0,
+ CP0MVPC0_PVPE, 4, smp_cpus - 1);
}
}
@@ -264,6 +264,26 @@ struct qemu_work_item;
#define CPU_UNSET_NUMA_NODE_ID -1
#define CPU_TRACE_DSTATE_MAX_EVENTS 32
+/**
+ * TopologyState:
+ * @sockets: Number of sockets within this machine.
+ * @cores_per_socket: Number of cores within this CPU socket.
+ * @threads_per_socket: Number of threads within this CPU socket.
+ * @dies_per_socket: Number of dies within this CPU socket.
+ * @clusters_per_die: Number of clusters within this CPU die.
+ * @cores_per_cluster: Number of cores within this CPU cluster.
+ * @threads_per_core: Number of threads within this CPU core.
+ */
+typedef struct TopologyState {
+ int sockets;
+ int cores_per_socket;
+ int threads_per_socket;
+ int dies_per_socket;
+ int clusters_per_die;
+ int cores_per_cluster;
+ int threads_per_core;
+} TopologyState;
+
/**
* CPUState:
* @cpu_index: CPU index (informative).
@@ -273,8 +293,7 @@ struct qemu_work_item;
* be the same as the cluster-id property of the CPU object's TYPE_CPU_CLUSTER
* QOM parent.
* @tcg_cflags: Pre-computed cflags for this cpu.
- * @nr_cores: Number of cores within this CPU package.
- * @nr_threads: Number of threads within this CPU core.
+ * @topo: Topology information of this cpu.
* @running: #true if CPU is currently running (lockless).
* @has_waiter: #true if a CPU is currently waiting for the cpu_exec_end;
* valid under cpu_list_lock.
@@ -327,8 +346,7 @@ struct CPUState {
CPUClass *cc;
/*< public >*/
- int nr_cores;
- int nr_threads;
+ TopologyState topo;
struct QemuThread *thread;
#ifdef _WIN32
@@ -626,12 +626,24 @@ const AccelOpsClass *cpus_get_accel(void)
return cpus_accel;
}
-void qemu_init_vcpu(CPUState *cpu)
+static void qemu_init_vcpu_topo(CPUState *cpu)
{
MachineState *ms = MACHINE(qdev_get_machine());
- cpu->nr_cores = machine_topo_get_cores_per_socket(ms);
- cpu->nr_threads = machine_topo_get_threads_by_idx(ms, cpu->cpu_index);
+ cpu->topo.sockets = machine_topo_get_sockets(ms);
+ cpu->topo.cores_per_socket = machine_topo_get_cores_per_socket(ms);
+ cpu->topo.threads_per_socket = machine_topo_get_threads_per_socket(ms);
+ cpu->topo.dies_per_socket = machine_topo_get_dies(ms);
+ cpu->topo.clusters_per_die = machine_topo_get_clusters(ms);
+ cpu->topo.cores_per_cluster =
+ machine_topo_get_cores_by_idx(ms, cpu->cpu_index);
+ cpu->topo.threads_per_core =
+ machine_topo_get_threads_by_idx(ms, cpu->cpu_index);
+}
+
+void qemu_init_vcpu(CPUState *cpu)
+{
+ qemu_init_vcpu_topo(cpu);
cpu->stopped = true;
cpu->random_seed = qemu_guest_random_seed_thread_part1();
@@ -5259,13 +5259,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
X86CPUTopoInfo topo_info;
uint32_t cpus_per_pkg;
- topo_info.dies_per_pkg = env->nr_dies;
- topo_info.modules_per_die = env->nr_modules;
- topo_info.cores_per_module = cs->nr_cores / env->nr_dies / env->nr_modules;
- topo_info.threads_per_core = cs->nr_threads;
+ topo_info.dies_per_pkg = cs->topo.dies_per_socket;
+ topo_info.modules_per_die = cs->topo.clusters_per_die;
+ topo_info.cores_per_module = cs->topo.cores_per_cluster;
+ topo_info.threads_per_core = cs->topo.threads_per_core;
- cpus_per_pkg = topo_info.dies_per_pkg * topo_info.modules_per_die *
- topo_info.cores_per_module * topo_info.threads_per_core;
+ cpus_per_pkg = cs->topo.threads_per_socket;
/* Calculate & apply limits for different index ranges */
if (index >= 0xC0000000) {
@@ -6687,14 +6686,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
* users a warning.
*
* NOTE: the following code has to follow qemu_init_vcpu(). Otherwise
- * cs->nr_threads hasn't be populated yet and the checking is incorrect.
+ * cs->topo.threads_per_core hasn't be populated yet and the checking is
+ * incorrect.
*/
if (IS_AMD_CPU(env) &&
!(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) &&
- cs->nr_threads > 1 && !ht_warned) {
+ cs->topo.threads_per_core > 1 && !ht_warned) {
warn_report("This family of AMD CPU doesn't support "
"hyperthreading(%d)",
- cs->nr_threads);
+ cs->topo.threads_per_core);
error_printf("Please configure -smp options properly"
" or try enabling topoext feature.\n");
ht_warned = true;
@@ -746,8 +746,10 @@ void simulate_rdmsr(struct CPUState *cpu)
val = env->mtrr_deftype;
break;
case MSR_CORE_THREAD_COUNT:
- val = cs->nr_threads * cs->nr_cores; /* thread count, bits 15..0 */
- val |= ((uint32_t)cs->nr_cores << 16); /* core count, bits 31..16 */
+ /* thread count, bits 15..0 */
+ val = cs->topo.threads_per_socket;
+ /* core count, bits 31..16 */
+ val |= ((uint32_t)cs->topo.cores_per_socket << 16);
break;
default:
/* fprintf(stderr, "%s: unknown msr 0x%x\n", __func__, msr); */
@@ -2416,8 +2416,10 @@ static bool kvm_rdmsr_core_thread_count(X86CPU *cpu, uint32_t msr,
{
CPUState *cs = CPU(cpu);
- *val = cs->nr_threads * cs->nr_cores; /* thread count, bits 15..0 */
- *val |= ((uint32_t)cs->nr_cores << 16); /* core count, bits 31..16 */
+ /* thread count, bits 15..0 */
+ *val = cs->topo.threads_per_socket;
+ /* core count, bits 31..16 */
+ *val |= ((uint32_t)cs->topo.cores_per_socket << 16);
return true;
}
@@ -452,7 +452,7 @@ void helper_rdmsr(CPUX86State *env)
break;
case MSR_CORE_THREAD_COUNT: {
CPUState *cs = CPU(x86_cpu);
- val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16);
+ val = (cs->topo.threads_per_socket) | (cs->topo.cores_per_socket << 16);
break;
}
default:
@@ -124,8 +124,8 @@ static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
}
cs = env_cpu(env);
- vpe_idx = tc_idx / cs->nr_threads;
- *tc = tc_idx % cs->nr_threads;
+ vpe_idx = tc_idx / cs->topo.threads_per_core;
+ *tc = tc_idx % cs->topo.threads_per_core;
other_cs = qemu_get_cpu(vpe_idx);
if (other_cs == NULL) {
return env;
@@ -232,7 +232,7 @@ int ppc_set_compat_all(uint32_t compat_pvr, Error **errp)
int ppc_compat_max_vthreads(PowerPCCPU *cpu)
{
const CompatInfo *compat = compat_by_pvr(cpu->compat_pvr);
- int n_threads = CPU(cpu)->nr_threads;
+ int n_threads = CPU(cpu)->topo.threads_per_core;
if (cpu->compat_pvr) {
g_assert(compat);