v2: fix compile error.
-----BEGIN PGP SIGNATURE----- iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCYymK3wAKCRBAov/yOSY+ 31trA/oDy6CHaPvT9mwKOM/ScYcwCf+dEtFGkqpsjcPlEB7GLJ9moJxp1xlm+Htw KA0MlA4QrI6MWd9udEbnoB7aRScG/ugzWHDPGocg+qjqiZvmHpE9ShdxYeDVJaLk 6hN9dkom+ANWeZ7T4gmdQreK/lwjUAqkiPSjw1HhvSHr3kAeDA== =uUxe -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20220920' of https://gitlab.com/gaosong/qemu into staging v2: fix compile error. # -----BEGIN PGP SIGNATURE----- # # iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCYymK3wAKCRBAov/yOSY+ # 31trA/oDy6CHaPvT9mwKOM/ScYcwCf+dEtFGkqpsjcPlEB7GLJ9moJxp1xlm+Htw # KA0MlA4QrI6MWd9udEbnoB7aRScG/ugzWHDPGocg+qjqiZvmHpE9ShdxYeDVJaLk # 6hN9dkom+ANWeZ7T4gmdQreK/lwjUAqkiPSjw1HhvSHr3kAeDA== # =uUxe # -----END PGP SIGNATURE----- # gpg: Signature made Tue 20 Sep 2022 05:41:51 EDT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Can't check signature: No public key * tag 'pull-loongarch-20220920' of https://gitlab.com/gaosong/qemu: hw/loongarch: Improve acpi dsdt table hw/loongarch: Support memory hotplug hw/loongarch: Fix acpi ged irq number in dsdt table hw/loongarch: Add RAMFB to dynamic_sysbus_devices list hw/loongarch: Add hotplug handler for machine hw/loongarch: Add platform bus support hw/loongarch: Add interrupt information to FDT table hw/loongarch: Support fw_cfg dma function hw/loongarch: Remove vga device when loongarch init Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
832e9e33bc
@ -2,13 +2,14 @@ config LOONGARCH_VIRT
|
||||
bool
|
||||
select PCI
|
||||
select PCI_EXPRESS_GENERIC_BRIDGE
|
||||
imply VGA_PCI
|
||||
imply VIRTIO_VGA
|
||||
imply PCI_DEVICES
|
||||
imply NVDIMM
|
||||
select ISA_BUS
|
||||
select SERIAL
|
||||
select SERIAL_ISA
|
||||
select VIRTIO_PCI
|
||||
select PLATFORM_BUS
|
||||
select LOONGARCH_IPI
|
||||
select LOONGARCH_PCH_PIC
|
||||
select LOONGARCH_PCH_MSI
|
||||
@ -17,3 +18,5 @@ config LOONGARCH_VIRT
|
||||
select SMBIOS
|
||||
select ACPI_PCI
|
||||
select ACPI_HW_REDUCED
|
||||
select FW_CFG_DMA
|
||||
select DIMM
|
||||
|
@ -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
|
||||
@ -186,6 +187,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);
|
||||
}
|
||||
|
||||
@ -200,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;
|
||||
@ -335,61 +240,55 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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_GED_EVT_ADDR);
|
||||
}
|
||||
|
||||
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);
|
||||
build_pci_device_aml(dsdt, lams);
|
||||
build_la_ged_aml(dsdt, machine);
|
||||
|
||||
/* System State Package */
|
||||
scope = aml_scope("\\");
|
||||
|
@ -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);
|
||||
|
@ -37,6 +37,10 @@
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include <libfdt.h>
|
||||
#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)
|
||||
{
|
||||
@ -118,7 +122,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);
|
||||
}
|
||||
@ -158,6 +162,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
|
||||
@ -318,6 +349,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;
|
||||
@ -331,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);
|
||||
@ -378,9 +435,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.
|
||||
@ -396,6 +450,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)
|
||||
@ -664,6 +720,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);
|
||||
@ -700,6 +785,11 @@ 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);
|
||||
@ -745,9 +835,105 @@ 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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
} else if (memhp_type_supported(dev)) {
|
||||
virt_mem_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
||||
DeviceState *dev)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
|
||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||
memhp_type_supported(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;
|
||||
@ -760,12 +946,18 @@ 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;
|
||||
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,
|
||||
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[] = {
|
||||
@ -775,6 +967,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 },
|
||||
{ }
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -49,6 +49,8 @@ struct LoongArchMachineState {
|
||||
char *oem_table_id;
|
||||
DeviceState *acpi_ged;
|
||||
int fdt_size;
|
||||
DeviceState *platform_bus_dev;
|
||||
PCIBus *pci_bus;
|
||||
};
|
||||
|
||||
#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user