mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 08:13:54 -06:00
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:
parent
087a23a87c
commit
8ccf28c2f6
2 changed files with 57 additions and 8 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue