hw/loongarch/virt: Implement cpu plug interface

Implement cpu plug interface, and cold-plug cpu uses plug interface
when cpu object is created.

Co-developed-by: Xianglai Li <lixianglai@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
This commit is contained in:
Bibo Mao 2025-02-10 15:21:39 +08:00
parent 2cd6857f6f
commit ab9935d299
2 changed files with 78 additions and 11 deletions

View file

@ -647,15 +647,13 @@ static void fw_cfg_add_memory(MachineState *ms)
static void virt_init(MachineState *machine) static void virt_init(MachineState *machine)
{ {
LoongArchCPU *lacpu;
const char *cpu_model = machine->cpu_type; const char *cpu_model = machine->cpu_type;
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine); LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
int i; int i;
hwaddr base, size, ram_size = machine->ram_size; hwaddr base, size, ram_size = machine->ram_size;
const CPUArchIdList *possible_cpus;
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
CPUState *cpu; Object *cpuobj;
if (!cpu_model) { if (!cpu_model) {
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464"); cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
@ -671,14 +669,15 @@ static void virt_init(MachineState *machine)
memory_region_add_subregion(&lvms->system_iocsr, 0, &lvms->iocsr_mem); memory_region_add_subregion(&lvms->system_iocsr, 0, &lvms->iocsr_mem);
/* Init CPUs */ /* Init CPUs */
possible_cpus = mc->possible_cpu_arch_ids(machine); mc->possible_cpu_arch_ids(machine);
for (i = 0; i < possible_cpus->len; i++) { for (i = 0; i < machine->smp.cpus; i++) {
cpu = cpu_create(machine->cpu_type); cpuobj = object_new(machine->cpu_type);
cpu->cpu_index = i; if (cpuobj == NULL) {
machine->possible_cpus->cpus[i].cpu = cpu; error_report("Fail to create object with type %s ",
lacpu = LOONGARCH_CPU(cpu); machine->cpu_type);
lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id; exit(EXIT_FAILURE);
lacpu->env.address_space_iocsr = &lvms->as_iocsr; }
qdev_realize_and_unref(DEVICE(cpuobj), NULL, &error_fatal);
} }
fw_cfg_add_memory(machine); fw_cfg_add_memory(machine);
@ -829,9 +828,52 @@ static CPUArchId *virt_find_cpu_slot(MachineState *ms, int arch_id)
return NULL; return NULL;
} }
/* Find cpu slot for cold-plut CPU object where cpu is NULL */
static CPUArchId *virt_find_empty_cpu_slot(MachineState *ms)
{
int n;
for (n = 0; n < ms->possible_cpus->len; n++) {
if (ms->possible_cpus->cpus[n].cpu == NULL) {
return &ms->possible_cpus->cpus[n];
}
}
return NULL;
}
static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
MachineState *ms = MACHINE(OBJECT(hotplug_dev));
LoongArchCPU *cpu = LOONGARCH_CPU(dev);
CPUState *cs = CPU(dev);
CPUArchId *cpu_slot;
Error *err = NULL;
LoongArchCPUTopo topo;
if (lvms->acpi_ged) {
error_setg(&err, "CPU hotplug not supported");
goto out;
} else {
/* For cold-add cpu, find empty cpu slot */
cpu_slot = virt_find_empty_cpu_slot(ms);
topo.socket_id = cpu_slot->props.socket_id;
topo.core_id = cpu_slot->props.core_id;
topo.thread_id = cpu_slot->props.thread_id;
object_property_set_int(OBJECT(dev), "socket-id", topo.socket_id, NULL);
object_property_set_int(OBJECT(dev), "core-id", topo.core_id, NULL);
object_property_set_int(OBJECT(dev), "thread-id", topo.thread_id, NULL);
}
cpu->env.address_space_iocsr = &lvms->as_iocsr;
cpu->phy_id = cpu_slot->arch_id;
cs->cpu_index = cpu_slot - ms->possible_cpus->cpus;
numa_cpu_pre_plug(cpu_slot, dev, &err);
out:
if (err) {
error_propagate(errp, err);
}
} }
static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev, static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
@ -892,6 +934,30 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
static void virt_cpu_plug(HotplugHandler *hotplug_dev, static void virt_cpu_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
CPUArchId *cpu_slot;
LoongArchCPU *cpu = LOONGARCH_CPU(dev);
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
Error *err = NULL;
cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id);
cpu_slot->cpu = CPU(dev);
if (lvms->ipi) {
hotplug_handler_plug(HOTPLUG_HANDLER(lvms->ipi), dev, &err);
if (err) {
error_propagate(errp, err);
return;
}
}
if (lvms->extioi) {
hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &err);
if (err) {
error_propagate(errp, err);
return;
}
}
return;
} }
static bool memhp_type_supported(DeviceState *dev) static bool memhp_type_supported(DeviceState *dev)

View file

@ -932,6 +932,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
#ifdef CONFIG_TCG #ifdef CONFIG_TCG
cc->tcg_ops = &loongarch_tcg_ops; cc->tcg_ops = &loongarch_tcg_ops;
#endif #endif
dc->user_creatable = true;
} }
static const gchar *loongarch32_gdb_arch_name(CPUState *cs) static const gchar *loongarch32_gdb_arch_name(CPUState *cs)