hw/loongarch/virt: Update the ACPI table for hotplug cpu
On LoongArch virt machine, ACPI GED hardware is used for CPU hotplug handler, here CPU hotplug support feature is added based on GED handler, also CPU scan and reject method is added about CPU device in DSDT table. Co-developed-by: Xianglai Li <lixianglai@loongson.cn> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
This commit is contained in:
parent
ab9935d299
commit
25cdac981f
@ -17,6 +17,7 @@ config LOONGARCH_VIRT
|
||||
select LOONGARCH_EXTIOI
|
||||
select LS7A_RTC
|
||||
select SMBIOS
|
||||
select ACPI_CPU_HOTPLUG
|
||||
select ACPI_PCI
|
||||
select ACPI_HW_REDUCED
|
||||
select FW_CFG_DMA
|
||||
|
@ -47,6 +47,22 @@
|
||||
#define ACPI_BUILD_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void virt_madt_cpu_entry(int uid,
|
||||
const CPUArchIdList *apic_ids,
|
||||
GArray *entry, bool force_enabled)
|
||||
{
|
||||
uint32_t flags, apic_id = apic_ids->cpus[uid].arch_id;
|
||||
|
||||
flags = apic_ids->cpus[uid].cpu || force_enabled ? 1 /* Enabled */ : 0;
|
||||
|
||||
/* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
|
||||
build_append_int_noprefix(entry, 0, 1); /* Type */
|
||||
build_append_int_noprefix(entry, 8, 1); /* Length */
|
||||
build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
|
||||
build_append_int_noprefix(entry, flags, 4); /* Flags */
|
||||
}
|
||||
|
||||
/* build FADT */
|
||||
static void init_common_fadt_data(AcpiFadtData *data)
|
||||
{
|
||||
@ -112,7 +128,7 @@ build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
|
||||
int i, arch_id;
|
||||
int i, arch_id, flags;
|
||||
AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lvms->oem_id,
|
||||
.oem_table_id = lvms->oem_table_id };
|
||||
|
||||
@ -125,13 +141,13 @@ build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
for (i = 0; i < arch_ids->len; i++) {
|
||||
/* Processor Core Interrupt Controller Structure */
|
||||
arch_id = arch_ids->cpus[i].arch_id;
|
||||
|
||||
flags = arch_ids->cpus[i].cpu ? 1 : 0;
|
||||
build_append_int_noprefix(table_data, 17, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 15, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Version */
|
||||
build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Flags */
|
||||
build_append_int_noprefix(table_data, flags, 4); /* Flags */
|
||||
}
|
||||
|
||||
/* Extend I/O Interrupt Controller Structure */
|
||||
@ -338,6 +354,7 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
|
||||
{
|
||||
uint32_t event;
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
CPUHotplugFeatures opts;
|
||||
|
||||
build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
|
||||
HOTPLUG_HANDLER(lvms->acpi_ged),
|
||||
@ -350,6 +367,18 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
|
||||
AML_SYSTEM_MEMORY,
|
||||
VIRT_GED_MEM_ADDR);
|
||||
}
|
||||
|
||||
if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
|
||||
opts.acpi_1_compatible = false;
|
||||
opts.has_legacy_cphp = false;
|
||||
opts.fw_unplugs_cpu = false;
|
||||
opts.smi_path = NULL;
|
||||
|
||||
build_cpus_aml(dsdt, machine, opts, virt_madt_cpu_entry,
|
||||
VIRT_GED_CPUHP_ADDR, "\\_SB",
|
||||
AML_GED_EVT_CPU_SCAN_METHOD, AML_SYSTEM_MEMORY);
|
||||
}
|
||||
|
||||
acpi_dsdt_add_power_button(dsdt);
|
||||
}
|
||||
|
||||
|
@ -187,11 +187,17 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic,
|
||||
{
|
||||
DeviceState *dev;
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(lvms);
|
||||
uint32_t event = ACPI_GED_PWR_DOWN_EVT;
|
||||
|
||||
if (ms->ram_slots) {
|
||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
||||
}
|
||||
|
||||
if (mc->has_hotpluggable_cpus) {
|
||||
event |= ACPI_GED_CPU_HOTPLUG_EVT;
|
||||
}
|
||||
|
||||
dev = qdev_new(TYPE_ACPI_GED);
|
||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
@ -203,6 +209,10 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic,
|
||||
/* ged regs used for reset and power down */
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);
|
||||
|
||||
if (mc->has_hotpluggable_cpus) {
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, VIRT_GED_CPUHP_ADDR);
|
||||
}
|
||||
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
|
||||
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - VIRT_GSI_BASE));
|
||||
return dev;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define VIRT_GED_EVT_ADDR 0x100e0000
|
||||
#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
|
||||
#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
|
||||
#define VIRT_GED_CPUHP_ADDR (VIRT_GED_REG_ADDR + ACPI_GED_REG_COUNT)
|
||||
|
||||
#define COMMAND_LINE_SIZE 512
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user