hw/loongarch/virt: Add CPU topology support

Add topological relationships for Loongarch VCPU and initialize
topology member variables.

On LoongArch system there is socket/core/thread topo information,
physical CPU id is calculated from CPU topo, every topo sub-field is
aligned by power of 2. So it is different from logical cpu index.

Co-developed-by: Xianglai Li <lixianglai@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
This commit is contained in:
Bibo Mao 2024-11-26 16:41:42 +08:00
parent 087a23a87c
commit 8ccf28c2f6
2 changed files with 57 additions and 8 deletions

View file

@ -774,6 +774,48 @@ static void virt_initfn(Object *obj)
virt_flash_create(lvms); virt_flash_create(lvms);
} }
static void virt_get_topo_from_index(MachineState *ms,
LoongArchCPUTopo *topo, int index)
{
topo->socket_id = index / (ms->smp.cores * ms->smp.threads);
topo->core_id = index / ms->smp.threads % ms->smp.cores;
topo->thread_id = index % ms->smp.threads;
}
static unsigned int topo_align_up(unsigned int count)
{
g_assert(count >= 1);
count -= 1;
return BIT(count ? 32 - clz32(count) : 0);
}
/*
* LoongArch Reference Manual Vol1, Chapter 7.4.12 CPU Identity
* For CPU architecture, bit0 .. bit8 is valid for CPU id, max cpuid is 512
* However for IPI/Eiointc interrupt controller, max supported cpu id for
* irq routingis 256
*
* Here max cpu id is 256 for virt machine
*/
static int virt_get_arch_id_from_topo(MachineState *ms, LoongArchCPUTopo *topo)
{
int arch_id, threads, cores, sockets;
threads = topo_align_up(ms->smp.threads);
cores = topo_align_up(ms->smp.cores);
sockets = topo_align_up(ms->smp.sockets);
if ((threads * cores * sockets) > 256) {
error_report("Exceeding max cpuid 256 with sockets[%d] cores[%d]"
" threads[%d]", ms->smp.sockets, ms->smp.cores,
ms->smp.threads);
exit(1);
}
arch_id = topo->thread_id + topo->core_id * threads;
arch_id += topo->socket_id * threads * cores;
return arch_id;
}
static bool memhp_type_supported(DeviceState *dev) static bool memhp_type_supported(DeviceState *dev)
{ {
/* we only support pc dimm now */ /* we only support pc dimm now */
@ -873,8 +915,9 @@ static HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
{ {
int n; int n, arch_id;
unsigned int max_cpus = ms->smp.max_cpus; unsigned int max_cpus = ms->smp.max_cpus;
LoongArchCPUTopo topo;
if (ms->possible_cpus) { if (ms->possible_cpus) {
assert(ms->possible_cpus->len == max_cpus); assert(ms->possible_cpus->len == max_cpus);
@ -885,17 +928,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
sizeof(CPUArchId) * max_cpus); sizeof(CPUArchId) * max_cpus);
ms->possible_cpus->len = max_cpus; ms->possible_cpus->len = max_cpus;
for (n = 0; n < ms->possible_cpus->len; n++) { for (n = 0; n < ms->possible_cpus->len; n++) {
virt_get_topo_from_index(ms, &topo, n);
arch_id = virt_get_arch_id_from_topo(ms, &topo);
ms->possible_cpus->cpus[n].type = ms->cpu_type; ms->possible_cpus->cpus[n].type = ms->cpu_type;
ms->possible_cpus->cpus[n].arch_id = n; ms->possible_cpus->cpus[n].arch_id = arch_id;
ms->possible_cpus->cpus[n].vcpus_count = 1;
ms->possible_cpus->cpus[n].props.has_socket_id = true; ms->possible_cpus->cpus[n].props.has_socket_id = true;
ms->possible_cpus->cpus[n].props.socket_id = ms->possible_cpus->cpus[n].props.socket_id = topo.socket_id;
n / (ms->smp.cores * ms->smp.threads);
ms->possible_cpus->cpus[n].props.has_core_id = true; ms->possible_cpus->cpus[n].props.has_core_id = true;
ms->possible_cpus->cpus[n].props.core_id = ms->possible_cpus->cpus[n].props.core_id = topo.core_id;
n / ms->smp.threads % ms->smp.cores;
ms->possible_cpus->cpus[n].props.has_thread_id = true; ms->possible_cpus->cpus[n].props.has_thread_id = true;
ms->possible_cpus->cpus[n].props.thread_id = n % ms->smp.threads; ms->possible_cpus->cpus[n].props.thread_id = topo.thread_id;
} }
return ms->possible_cpus; return ms->possible_cpus;
} }

View file

@ -393,6 +393,12 @@ typedef struct CPUArchState {
#endif #endif
} CPULoongArchState; } CPULoongArchState;
typedef struct LoongArchCPUTopo {
int32_t socket_id; /* socket-id of this VCPU */
int32_t core_id; /* core-id of this VCPU */
int32_t thread_id; /* thread-id of this VCPU */
} LoongArchCPUTopo;
/** /**
* LoongArchCPU: * LoongArchCPU:
* @env: #CPULoongArchState * @env: #CPULoongArchState