From 3ff17902c48bfb4e7ce20acf6f00c33fb6e0ed60 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:38:03 +0800 Subject: [PATCH 1/9] hw/loongarch: Remove vga device when loongarch init Remove the vga device when loongarch machine init and we will support other display device in the future. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-2-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 - hw/loongarch/virt.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index a99aa387c3..73c52b093e 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -2,7 +2,6 @@ config LOONGARCH_VIRT bool select PCI select PCI_EXPRESS_GENERIC_BRIDGE - imply VGA_PCI imply VIRTIO_VGA imply PCI_DEVICES select ISA_BUS diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 5cc0b05538..b56820ecda 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -378,9 +378,6 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); } - /* VGA setup */ - pci_vga_init(pci_bus); - /* * There are some invalid guest memory access. * Create some unimplemented devices to emulate this. From feae45dc427ed8e0cf01e4730f2f798374536137 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:53:36 +0800 Subject: [PATCH 2/9] hw/loongarch: Support fw_cfg dma function Support fw_cfg dma function for LoongArch virt machine. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-3-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 + hw/loongarch/fw_cfg.c | 3 ++- hw/loongarch/virt.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 73c52b093e..1deea83626 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -16,3 +16,4 @@ config LOONGARCH_VIRT select SMBIOS select ACPI_PCI select ACPI_HW_REDUCED + select FW_CFG_DMA diff --git a/hw/loongarch/fw_cfg.c b/hw/loongarch/fw_cfg.c index f6503d5607..f15a17416c 100644 --- a/hw/loongarch/fw_cfg.c +++ b/hw/loongarch/fw_cfg.c @@ -23,7 +23,8 @@ FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, MachineState *ms) int max_cpus = ms->smp.max_cpus; int smp_cpus = ms->smp.cpus; - fw_cfg = fw_cfg_init_mem_wide(VIRT_FWCFG_BASE + 8, VIRT_FWCFG_BASE, 8, 0, NULL); + fw_cfg = fw_cfg_init_mem_wide(VIRT_FWCFG_BASE + 8, VIRT_FWCFG_BASE, 8, + VIRT_FWCFG_BASE + 16, &address_space_memory); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index b56820ecda..4f833a2044 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -118,7 +118,7 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams) qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "qemu,fw-cfg-mmio"); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", - 2, base, 2, 0x8); + 2, base, 2, 0x18); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0); g_free(nodename); } From ee413a52c1bc36abbdbf097da0c9143b9a88220d Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:33:57 +0800 Subject: [PATCH 3/9] hw/loongarch: Add interrupt information to FDT table Add interrupt information to FDT table, such as interrupt controller info, compatiable info, etc. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-4-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 4f833a2044..68b59a6c9f 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -158,6 +158,33 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams) qemu_fdt_dumpdtb(ms->fdt, lams->fdt_size); } +static void fdt_add_irqchip_node(LoongArchMachineState *lams) +{ + MachineState *ms = MACHINE(lams); + char *nodename; + uint32_t irqchip_phandle; + + irqchip_phandle = qemu_fdt_alloc_phandle(ms->fdt); + qemu_fdt_setprop_cell(ms->fdt, "/", "interrupt-parent", irqchip_phandle); + + nodename = g_strdup_printf("/intc@%lx", VIRT_IOAPIC_REG_BASE); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 3); + qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2); + qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0); + + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", + "loongarch,ls7a"); + + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", + 2, VIRT_IOAPIC_REG_BASE, + 2, PCH_PIC_ROUTE_ENTRY_OFFSET); + + qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", irqchip_phandle); + g_free(nodename); +} #define PM_BASE 0x10080000 #define PM_SIZE 0x100 @@ -697,6 +724,7 @@ static void loongarch_init(MachineState *machine) } /* Initialize the IO interrupt subsystem */ loongarch_irq_init(lams); + fdt_add_irqchip_node(lams); lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); fdt_add_pcie_node(lams); From a1f7d78e564a453ea07159efaa1af9a7210ddeda Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:50:35 +0800 Subject: [PATCH 4/9] hw/loongarch: Add platform bus support Add platform bus support and add the bus information such as address, size, irq number to FDT table. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-5-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 + hw/loongarch/virt.c | 33 +++++++++++++++++++++++++++++++++ include/hw/loongarch/virt.h | 1 + include/hw/pci-host/ls7a.h | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 1deea83626..fef55c5638 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -8,6 +8,7 @@ config LOONGARCH_VIRT select SERIAL select SERIAL_ISA select VIRTIO_PCI + select PLATFORM_BUS select LOONGARCH_IPI select LOONGARCH_PCH_PIC select LOONGARCH_PCH_MSI diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 68b59a6c9f..5fd3834c0a 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -37,6 +37,8 @@ #include "hw/mem/nvdimm.h" #include "sysemu/device_tree.h" #include +#include "hw/core/sysbus-fdt.h" +#include "hw/platform-bus.h" static void create_fdt(LoongArchMachineState *lams) { @@ -345,6 +347,31 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState return dev; } +static DeviceState *create_platform_bus(DeviceState *pch_pic) +{ + DeviceState *dev; + SysBusDevice *sysbus; + int i, irq; + MemoryRegion *sysmem = get_system_memory(); + + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); + dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE); + qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS); + qdev_prop_set_uint32(dev, "mmio_size", VIRT_PLATFORM_BUS_SIZE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + sysbus = SYS_BUS_DEVICE(dev); + for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) { + irq = VIRT_PLATFORM_BUS_IRQ - PCH_PIC_IRQ_OFFSET + i; + sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(pch_pic, irq)); + } + + memory_region_add_subregion(sysmem, + VIRT_PLATFORM_BUS_BASEADDRESS, + sysbus_mmio_get_region(sysbus, 0)); + return dev; +} + static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *lams) { DeviceState *gpex_dev; @@ -420,6 +447,8 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * memory_region_add_subregion(get_system_memory(), PM_BASE, pm_mem); /* acpi ged */ lams->acpi_ged = create_acpi_ged(pch_pic, lams); + /* platform bus */ + lams->platform_bus_dev = create_platform_bus(pch_pic); } static void loongarch_irq_init(LoongArchMachineState *lams) @@ -725,6 +754,10 @@ static void loongarch_init(MachineState *machine) /* Initialize the IO interrupt subsystem */ loongarch_irq_init(lams); fdt_add_irqchip_node(lams); + platform_bus_add_all_fdt_nodes(machine->fdt, "/intc", + VIRT_PLATFORM_BUS_BASEADDRESS, + VIRT_PLATFORM_BUS_SIZE, + VIRT_PLATFORM_BUS_IRQ); lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); fdt_add_pcie_node(lams); diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 92b84de1c5..64c90b80d2 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -49,6 +49,7 @@ struct LoongArchMachineState { char *oem_table_id; DeviceState *acpi_ged; int fdt_size; + DeviceState *platform_bus_dev; }; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt") diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index cdde0af1f8..9bd875ca8b 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -42,4 +42,9 @@ #define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) #define VIRT_RTC_LEN 0x100 #define VIRT_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4) + +#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 +#define VIRT_PLATFORM_BUS_SIZE 0x2000000 +#define VIRT_PLATFORM_BUS_NUM_IRQS 2 +#define VIRT_PLATFORM_BUS_IRQ 69 #endif From e27e535768129834cf6debed4575a161f7013dda Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:37:21 +0800 Subject: [PATCH 5/9] hw/loongarch: Add hotplug handler for machine Add hotplug handler for LoongArch virt machine and now only support the dynamic sysbus device. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-6-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 5fd3834c0a..eedff10758 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -803,9 +803,35 @@ static void loongarch_machine_initfn(Object *obj) lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } +static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + MachineClass *mc = MACHINE_GET_CLASS(lams); + + if (device_is_dynamic_sysbus(mc, dev)) { + if (lams->platform_bus_dev) { + platform_bus_link_device(PLATFORM_BUS_DEVICE(lams->platform_bus_dev), + SYS_BUS_DEVICE(dev)); + } + } +} + +static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (device_is_dynamic_sysbus(mc, dev)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + static void loongarch_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->desc = "Loongson-3A5000 LS7A1000 machine"; mc->init = loongarch_init; @@ -818,6 +844,8 @@ static void loongarch_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_VIRTIO; mc->default_boot_order = "c"; mc->no_cdrom = 1; + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + hc->plug = loongarch_machine_device_plug_cb; object_class_property_add(oc, "acpi", "OnOffAuto", loongarch_get_acpi, loongarch_set_acpi, @@ -833,6 +861,10 @@ static const TypeInfo loongarch_machine_types[] = { .instance_size = sizeof(LoongArchMachineState), .class_init = loongarch_class_init, .instance_init = loongarch_machine_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, } }; From f8ab9aa2883c91fb14eb583febf6a301373c8f62 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:41:52 +0800 Subject: [PATCH 6/9] hw/loongarch: Add RAMFB to dynamic_sysbus_devices list Add RAMFB device to dynamic_sysbus_devices list so that it can be hotpluged to the machine. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-7-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index eedff10758..0dd57935b0 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -39,6 +39,7 @@ #include #include "hw/core/sysbus-fdt.h" #include "hw/platform-bus.h" +#include "hw/display/ramfb.h" static void create_fdt(LoongArchMachineState *lams) { @@ -852,6 +853,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data) NULL, NULL); object_class_property_set_description(oc, "acpi", "Enable ACPI"); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); } static const TypeInfo loongarch_machine_types[] = { From 1cd5db2e8836dc2e1e8fe83f6a2fc101c539df0c Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Fri, 19 Aug 2022 11:16:37 +0800 Subject: [PATCH 7/9] hw/loongarch: Fix acpi ged irq number in dsdt table In dsdt, acpi ged irq should use gsi number, and the VIRT_SCI_IRQ means it. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-8-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/acpi-build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index d0f01a6485..95e30975a8 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -367,7 +367,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) if (lams->acpi_ged) { build_ged_aml(dsdt, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(lams->acpi_ged), - VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET, AML_SYSTEM_MEMORY, + VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, VIRT_GED_EVT_ADDR); } From c3da26f314ad918ad36ca1373ea7c7f1aa036a87 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Thu, 25 Aug 2022 11:36:59 +0800 Subject: [PATCH 8/9] hw/loongarch: Support memory hotplug Add hotplug/unplug interface for memory device. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-9-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 2 + hw/loongarch/acpi-build.c | 32 +++++++++--- hw/loongarch/virt.c | 105 +++++++++++++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 7 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index fef55c5638..17d15b6c90 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -4,6 +4,7 @@ config LOONGARCH_VIRT select PCI_EXPRESS_GENERIC_BRIDGE imply VIRTIO_VGA imply PCI_DEVICES + imply NVDIMM select ISA_BUS select SERIAL select SERIAL_ISA @@ -18,3 +19,4 @@ config LOONGARCH_VIRT select ACPI_PCI select ACPI_HW_REDUCED select FW_CFG_DMA + select DIMM diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 95e30975a8..92ee62c11a 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -186,6 +186,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_srat_memory(table_data, VIRT_HIGHMEM_BASE, machine->ram_size - VIRT_LOWMEM_SIZE, 0, MEM_AFFINITY_ENABLED); + if (ms->device_memory) { + build_srat_memory(table_data, ms->device_memory->base, + memory_region_size(&ms->device_memory->mr), + 0, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); + } + acpi_table_end(linker, &table); } @@ -335,6 +341,25 @@ static void build_uart_device_aml(Aml *table) aml_append(table, scope); } +static void +build_la_ged_aml(Aml *dsdt, MachineState *machine) +{ + uint32_t event; + LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); + + build_ged_aml(dsdt, "\\_SB."GED_DEVICE, + HOTPLUG_HANDLER(lams->acpi_ged), + VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, + VIRT_GED_EVT_ADDR); + event = object_property_get_uint(OBJECT(lams->acpi_ged), + "ged-event", &error_abort); + if (event & ACPI_GED_MEM_HOTPLUG_EVT) { + build_memory_hotplug_aml(dsdt, machine->ram_slots, "\\_SB", NULL, + AML_SYSTEM_MEMORY, + VIRT_GED_MEM_ADDR); + } +} + /* build DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) @@ -364,12 +389,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_gpex_pci0_int(dsdt); build_uart_device_aml(dsdt); - if (lams->acpi_ged) { - build_ged_aml(dsdt, "\\_SB."GED_DEVICE, - HOTPLUG_HANDLER(lams->acpi_ged), - VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, - VIRT_GED_EVT_ADDR); - } + build_la_ged_aml(dsdt, machine); scope = aml_scope("\\_SB.PCI0"); /* Build PCI0._CRS */ diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 0dd57935b0..fe175e873b 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -40,6 +40,7 @@ #include "hw/core/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/display/ramfb.h" +#include "hw/mem/pc-dimm.h" static void create_fdt(LoongArchMachineState *lams) { @@ -718,6 +719,35 @@ static void loongarch_init(MachineState *machine) machine->ram, offset, highram_size); memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem); memmap_add_entry(0x90000000, highram_size, 1); + + /* initialize device memory address space */ + if (machine->ram_size < machine->maxram_size) { + machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); + ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; + + if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) { + error_report("unsupported amount of memory slots: %"PRIu64, + machine->ram_slots); + exit(EXIT_FAILURE); + } + + if (QEMU_ALIGN_UP(machine->maxram_size, + TARGET_PAGE_SIZE) != machine->maxram_size) { + error_report("maximum memory size must by aligned to multiple of " + "%d bytes", TARGET_PAGE_SIZE); + exit(EXIT_FAILURE); + } + /* device memory base is the top of high memory address. */ + machine->device_memory->base = 0x90000000 + highram_size; + machine->device_memory->base = + ROUND_UP(machine->device_memory->base, 1 * GiB); + + memory_region_init(&machine->device_memory->mr, OBJECT(lams), + "device-memory", device_mem_size); + memory_region_add_subregion(address_space_mem, machine->device_memory->base, + &machine->device_memory->mr); + } + /* Add isa io region */ memory_region_init_alias(&lams->isa_io, NULL, "isa-io", get_system_io(), 0, VIRT_ISA_IO_SIZE); @@ -804,6 +834,73 @@ static void loongarch_machine_initfn(Object *obj) lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } +static bool memhp_type_supported(DeviceState *dev) +{ + /* we only support pc dimm now */ + return object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && + !object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); +} + +static void virt_mem_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); +} + +static void virt_machine_device_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_pre_plug(hotplug_dev, dev, errp); + } +} + +static void virt_mem_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + /* the acpi ged is always exist */ + hotplug_handler_unplug_request(HOTPLUG_HANDLER(lams->acpi_ged), dev, + errp); +} + +static void virt_machine_device_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_unplug_request(hotplug_dev, dev, errp); + } +} + +static void virt_mem_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + hotplug_handler_unplug(HOTPLUG_HANDLER(lams->acpi_ged), dev, errp); + pc_dimm_unplug(PC_DIMM(dev), MACHINE(lams)); + qdev_unrealize(dev); +} + +static void virt_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_unplug(hotplug_dev, dev, errp); + } +} + +static void virt_mem_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + pc_dimm_plug(PC_DIMM(dev), MACHINE(lams)); + hotplug_handler_plug(HOTPLUG_HANDLER(lams->acpi_ged), + dev, &error_abort); +} + static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -815,6 +912,8 @@ static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, platform_bus_link_device(PLATFORM_BUS_DEVICE(lams->platform_bus_dev), SYS_BUS_DEVICE(dev)); } + } else if (memhp_type_supported(dev)) { + virt_mem_plug(hotplug_dev, dev, errp); } } @@ -823,7 +922,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, { MachineClass *mc = MACHINE_GET_CLASS(machine); - if (device_is_dynamic_sysbus(mc, dev)) { + if (device_is_dynamic_sysbus(mc, dev) || + memhp_type_supported(dev)) { return HOTPLUG_HANDLER(machine); } return NULL; @@ -847,6 +947,9 @@ static void loongarch_class_init(ObjectClass *oc, void *data) mc->no_cdrom = 1; mc->get_hotplug_handler = virt_machine_get_hotplug_handler; hc->plug = loongarch_machine_device_plug_cb; + hc->pre_plug = virt_machine_device_pre_plug; + hc->unplug_request = virt_machine_device_unplug_request; + hc->unplug = virt_machine_device_unplug; object_class_property_add(oc, "acpi", "OnOffAuto", loongarch_get_acpi, loongarch_set_acpi, From 1895b967922890f76ad0ba8eefad6019e0328606 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Thu, 25 Aug 2022 11:57:33 +0800 Subject: [PATCH 9/9] hw/loongarch: Improve acpi dsdt table Cleanup the previous pci information in acpi dsdt table. And using the common acpi_dsdt_add_gpex function to build the gpex and pci information. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-10-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/acpi-build.c | 159 +++++------------------------------- hw/loongarch/virt.c | 1 + include/hw/loongarch/virt.h | 1 + 3 files changed, 21 insertions(+), 140 deletions(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 92ee62c11a..378a6d9d38 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -30,6 +30,7 @@ #include "qom/qom-qobject.h" #include "hw/acpi/generic_event_device.h" +#include "hw/pci-host/gpex.h" #define ACPI_BUILD_ALIGN_SIZE 0x1000 #define ACPI_BUILD_TABLE_SIZE 0x20000 @@ -206,108 +207,6 @@ struct AcpiBuildState { MemoryRegion *linker_mr; } AcpiBuildState; -static void build_gpex_pci0_int(Aml *table) -{ - Aml *sb_scope = aml_scope("_SB"); - Aml *pci0_scope = aml_scope("PCI0"); - Aml *prt_pkg = aml_varpackage(128); - int slot, pin; - - for (slot = 0; slot < PCI_SLOT_MAX; slot++) { - for (pin = 0; pin < PCI_NUM_PINS; pin++) { - Aml *pkg = aml_package(4); - aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); - aml_append(pkg, aml_int(pin)); - aml_append(pkg, aml_int(0)); - aml_append(pkg, aml_int(80 + (slot + pin) % 4)); - aml_append(prt_pkg, pkg); - } - } - aml_append(pci0_scope, aml_name_decl("_PRT", prt_pkg)); - aml_append(sb_scope, pci0_scope); - aml_append(table, sb_scope); -} - -static void build_dbg_aml(Aml *table) -{ - Aml *field; - Aml *method; - Aml *while_ctx; - Aml *scope = aml_scope("\\"); - Aml *buf = aml_local(0); - Aml *len = aml_local(1); - Aml *idx = aml_local(2); - - aml_append(scope, - aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); - field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); - aml_append(field, aml_named_field("DBGB", 8)); - aml_append(scope, field); - - method = aml_method("DBUG", 1, AML_NOTSERIALIZED); - - aml_append(method, aml_to_hexstring(aml_arg(0), buf)); - aml_append(method, aml_to_buffer(buf, buf)); - aml_append(method, aml_subtract(aml_sizeof(buf), aml_int(1), len)); - aml_append(method, aml_store(aml_int(0), idx)); - - while_ctx = aml_while(aml_lless(idx, len)); - aml_append(while_ctx, - aml_store(aml_derefof(aml_index(buf, idx)), aml_name("DBGB"))); - aml_append(while_ctx, aml_increment(idx)); - aml_append(method, while_ctx); - aml_append(method, aml_store(aml_int(0x0A), aml_name("DBGB"))); - aml_append(scope, method); - aml_append(table, scope); -} - -static Aml *build_osc_method(void) -{ - Aml *if_ctx; - Aml *if_ctx2; - Aml *else_ctx; - Aml *method; - Aml *a_cwd1 = aml_name("CDW1"); - Aml *a_ctrl = aml_local(0); - - method = aml_method("_OSC", 4, AML_NOTSERIALIZED); - aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); - - if_ctx = aml_if(aml_equal( - aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"))); - aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); - aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); - aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl)); - - /* - * Always allow native PME, AER (no dependencies) - * Allow SHPC (PCI bridges can have SHPC controller) - */ - aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); - - if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1)))); - /* Unknown revision */ - aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1)); - aml_append(if_ctx, if_ctx2); - - if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl))); - /* Capabilities bits were masked */ - aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1)); - aml_append(if_ctx, if_ctx2); - - /* Update DWORD3 in the buffer */ - aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3"))); - aml_append(method, if_ctx); - - else_ctx = aml_else(); - /* Unrecognized UUID */ - aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1)); - aml_append(method, else_ctx); - - aml_append(method, aml_return(aml_arg(3))); - return method; -} - static void build_uart_device_aml(Aml *table) { Aml *dev; @@ -360,57 +259,37 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine) } } +static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) +{ + struct GPEXConfig cfg = { + .mmio64.base = VIRT_PCI_MEM_BASE, + .mmio64.size = VIRT_PCI_MEM_SIZE, + .pio.base = VIRT_PCI_IO_BASE, + .pio.size = VIRT_PCI_IO_SIZE, + .ecam.base = VIRT_PCI_CFG_BASE, + .ecam.size = VIRT_PCI_CFG_SIZE, + .irq = PCH_PIC_IRQ_OFFSET + VIRT_DEVICE_IRQS, + .bus = lams->pci_bus, + }; + + acpi_dsdt_add_gpex(scope, &cfg); +} + /* build DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) { - Aml *dsdt, *sb_scope, *scope, *dev, *crs, *pkg; - int root_bus_limit = 0x7F; + Aml *dsdt, *scope, *pkg; LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lams->oem_id, .oem_table_id = lams->oem_table_id }; acpi_table_begin(&table, table_data); - dsdt = init_aml_allocator(); - - build_dbg_aml(dsdt); - - sb_scope = aml_scope("_SB"); - dev = aml_device("PCI0"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); - aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); - aml_append(dev, aml_name_decl("_ADR", aml_int(0))); - aml_append(dev, aml_name_decl("_BBN", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_int(1))); - aml_append(dev, build_osc_method()); - aml_append(sb_scope, dev); - aml_append(dsdt, sb_scope); - - build_gpex_pci0_int(dsdt); build_uart_device_aml(dsdt); + build_pci_device_aml(dsdt, lams); build_la_ged_aml(dsdt, machine); - scope = aml_scope("\\_SB.PCI0"); - /* Build PCI0._CRS */ - crs = aml_resource_template(); - aml_append(crs, - aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - 0x0000, 0x0, root_bus_limit, - 0x0000, root_bus_limit + 1)); - aml_append(crs, - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, - AML_POS_DECODE, AML_ENTIRE_RANGE, - 0x0000, 0x0000, 0xFFFF, 0x18000000, 0x10000)); - aml_append(crs, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_CACHEABLE, AML_READ_WRITE, - 0, VIRT_PCI_MEM_BASE, - VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1, - 0, VIRT_PCI_MEM_BASE)); - aml_append(scope, aml_name_decl("_CRS", crs)); - aml_append(dsdt, scope); - /* System State Package */ scope = aml_scope("\\"); pkg = aml_package(4); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index fe175e873b..29df99727d 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -387,6 +387,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * d = SYS_BUS_DEVICE(gpex_dev); sysbus_realize_and_unref(d, &error_fatal); pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus; + lams->pci_bus = pci_bus; /* Map only part size_ecam bytes of ECAM space */ ecam_alias = g_new0(MemoryRegion, 1); diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 64c90b80d2..09f1c88ee5 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -50,6 +50,7 @@ struct LoongArchMachineState { DeviceState *acpi_ged; int fdt_size; DeviceState *platform_bus_dev; + PCIBus *pci_bus; }; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")