qemu

Форк
0
/
virt.c 
1442 строки · 49.8 Кб
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
/*
3
 * QEMU loongson 3a5000 develop board emulation
4
 *
5
 * Copyright (c) 2021 Loongson Technology Corporation Limited
6
 */
7
#include "qemu/osdep.h"
8
#include "qemu/units.h"
9
#include "qemu/datadir.h"
10
#include "qapi/error.h"
11
#include "hw/boards.h"
12
#include "hw/char/serial.h"
13
#include "sysemu/kvm.h"
14
#include "sysemu/tcg.h"
15
#include "sysemu/sysemu.h"
16
#include "sysemu/qtest.h"
17
#include "sysemu/runstate.h"
18
#include "sysemu/reset.h"
19
#include "sysemu/rtc.h"
20
#include "hw/loongarch/virt.h"
21
#include "exec/address-spaces.h"
22
#include "hw/irq.h"
23
#include "net/net.h"
24
#include "hw/loader.h"
25
#include "elf.h"
26
#include "hw/intc/loongarch_ipi.h"
27
#include "hw/intc/loongarch_extioi.h"
28
#include "hw/intc/loongarch_pch_pic.h"
29
#include "hw/intc/loongarch_pch_msi.h"
30
#include "hw/pci-host/ls7a.h"
31
#include "hw/pci-host/gpex.h"
32
#include "hw/misc/unimp.h"
33
#include "hw/loongarch/fw_cfg.h"
34
#include "target/loongarch/cpu.h"
35
#include "hw/firmware/smbios.h"
36
#include "hw/acpi/aml-build.h"
37
#include "qapi/qapi-visit-common.h"
38
#include "hw/acpi/generic_event_device.h"
39
#include "hw/mem/nvdimm.h"
40
#include "sysemu/device_tree.h"
41
#include <libfdt.h>
42
#include "hw/core/sysbus-fdt.h"
43
#include "hw/platform-bus.h"
44
#include "hw/display/ramfb.h"
45
#include "hw/mem/pc-dimm.h"
46
#include "sysemu/tpm.h"
47
#include "sysemu/block-backend.h"
48
#include "hw/block/flash.h"
49
#include "hw/virtio/virtio-iommu.h"
50
#include "qemu/error-report.h"
51

52
static bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
53
{
54
    if (lvms->veiointc == ON_OFF_AUTO_OFF) {
55
        return false;
56
    }
57
    return true;
58
}
59

60
static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
61
                              void *opaque, Error **errp)
62
{
63
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
64
    OnOffAuto veiointc = lvms->veiointc;
65

66
    visit_type_OnOffAuto(v, name, &veiointc, errp);
67
}
68

69
static void virt_set_veiointc(Object *obj, Visitor *v, const char *name,
70
                              void *opaque, Error **errp)
71
{
72
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
73

74
    visit_type_OnOffAuto(v, name, &lvms->veiointc, errp);
75
}
76

77
static PFlashCFI01 *virt_flash_create1(LoongArchVirtMachineState *lvms,
78
                                       const char *name,
79
                                       const char *alias_prop_name)
80
{
81
    DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
82

83
    qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
84
    qdev_prop_set_uint8(dev, "width", 4);
85
    qdev_prop_set_uint8(dev, "device-width", 2);
86
    qdev_prop_set_bit(dev, "big-endian", false);
87
    qdev_prop_set_uint16(dev, "id0", 0x89);
88
    qdev_prop_set_uint16(dev, "id1", 0x18);
89
    qdev_prop_set_uint16(dev, "id2", 0x00);
90
    qdev_prop_set_uint16(dev, "id3", 0x00);
91
    qdev_prop_set_string(dev, "name", name);
92
    object_property_add_child(OBJECT(lvms), name, OBJECT(dev));
93
    object_property_add_alias(OBJECT(lvms), alias_prop_name,
94
                              OBJECT(dev), "drive");
95
    return PFLASH_CFI01(dev);
96
}
97

98
static void virt_flash_create(LoongArchVirtMachineState *lvms)
99
{
100
    lvms->flash[0] = virt_flash_create1(lvms, "virt.flash0", "pflash0");
101
    lvms->flash[1] = virt_flash_create1(lvms, "virt.flash1", "pflash1");
102
}
103

104
static void virt_flash_map1(PFlashCFI01 *flash,
105
                            hwaddr base, hwaddr size,
106
                            MemoryRegion *sysmem)
107
{
108
    DeviceState *dev = DEVICE(flash);
109
    BlockBackend *blk;
110
    hwaddr real_size = size;
111

112
    blk = pflash_cfi01_get_blk(flash);
113
    if (blk) {
114
        real_size = blk_getlength(blk);
115
        assert(real_size && real_size <= size);
116
    }
117

118
    assert(QEMU_IS_ALIGNED(real_size, VIRT_FLASH_SECTOR_SIZE));
119
    assert(real_size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
120

121
    qdev_prop_set_uint32(dev, "num-blocks", real_size / VIRT_FLASH_SECTOR_SIZE);
122
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
123
    memory_region_add_subregion(sysmem, base,
124
                                sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
125
}
126

127
static void virt_flash_map(LoongArchVirtMachineState *lvms,
128
                           MemoryRegion *sysmem)
129
{
130
    PFlashCFI01 *flash0 = lvms->flash[0];
131
    PFlashCFI01 *flash1 = lvms->flash[1];
132

133
    virt_flash_map1(flash0, VIRT_FLASH0_BASE, VIRT_FLASH0_SIZE, sysmem);
134
    virt_flash_map1(flash1, VIRT_FLASH1_BASE, VIRT_FLASH1_SIZE, sysmem);
135
}
136

137
static void fdt_add_cpuic_node(LoongArchVirtMachineState *lvms,
138
                               uint32_t *cpuintc_phandle)
139
{
140
    MachineState *ms = MACHINE(lvms);
141
    char *nodename;
142

143
    *cpuintc_phandle = qemu_fdt_alloc_phandle(ms->fdt);
144
    nodename = g_strdup_printf("/cpuic");
145
    qemu_fdt_add_subnode(ms->fdt, nodename);
146
    qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *cpuintc_phandle);
147
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
148
                            "loongson,cpu-interrupt-controller");
149
    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
150
    qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
151
    g_free(nodename);
152
}
153

154
static void fdt_add_eiointc_node(LoongArchVirtMachineState *lvms,
155
                                  uint32_t *cpuintc_phandle,
156
                                  uint32_t *eiointc_phandle)
157
{
158
    MachineState *ms = MACHINE(lvms);
159
    char *nodename;
160
    hwaddr extioi_base = APIC_BASE;
161
    hwaddr extioi_size = EXTIOI_SIZE;
162

163
    *eiointc_phandle = qemu_fdt_alloc_phandle(ms->fdt);
164
    nodename = g_strdup_printf("/eiointc@%" PRIx64, extioi_base);
165
    qemu_fdt_add_subnode(ms->fdt, nodename);
166
    qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *eiointc_phandle);
167
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
168
                            "loongson,ls2k2000-eiointc");
169
    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
170
    qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
171
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
172
                          *cpuintc_phandle);
173
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", 3);
174
    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0,
175
                           extioi_base, 0x0, extioi_size);
176
    g_free(nodename);
177
}
178

179
static void fdt_add_pch_pic_node(LoongArchVirtMachineState *lvms,
180
                                 uint32_t *eiointc_phandle,
181
                                 uint32_t *pch_pic_phandle)
182
{
183
    MachineState *ms = MACHINE(lvms);
184
    char *nodename;
185
    hwaddr pch_pic_base = VIRT_PCH_REG_BASE;
186
    hwaddr pch_pic_size = VIRT_PCH_REG_SIZE;
187

188
    *pch_pic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
189
    nodename = g_strdup_printf("/platic@%" PRIx64, pch_pic_base);
190
    qemu_fdt_add_subnode(ms->fdt, nodename);
191
    qemu_fdt_setprop_cell(ms->fdt,  nodename, "phandle", *pch_pic_phandle);
192
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
193
                            "loongson,pch-pic-1.0");
194
    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0,
195
                           pch_pic_base, 0, pch_pic_size);
196
    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
197
    qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 2);
198
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
199
                          *eiointc_phandle);
200
    qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,pic-base-vec", 0);
201
    g_free(nodename);
202
}
203

204
static void fdt_add_pch_msi_node(LoongArchVirtMachineState *lvms,
205
                                 uint32_t *eiointc_phandle,
206
                                 uint32_t *pch_msi_phandle)
207
{
208
    MachineState *ms = MACHINE(lvms);
209
    char *nodename;
210
    hwaddr pch_msi_base = VIRT_PCH_MSI_ADDR_LOW;
211
    hwaddr pch_msi_size = VIRT_PCH_MSI_SIZE;
212

213
    *pch_msi_phandle = qemu_fdt_alloc_phandle(ms->fdt);
214
    nodename = g_strdup_printf("/msi@%" PRIx64, pch_msi_base);
215
    qemu_fdt_add_subnode(ms->fdt, nodename);
216
    qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *pch_msi_phandle);
217
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
218
                            "loongson,pch-msi-1.0");
219
    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg",
220
                           0, pch_msi_base,
221
                           0, pch_msi_size);
222
    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
223
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
224
                          *eiointc_phandle);
225
    qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,msi-base-vec",
226
                          VIRT_PCH_PIC_IRQ_NUM);
227
    qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,msi-num-vecs",
228
                          EXTIOI_IRQS - VIRT_PCH_PIC_IRQ_NUM);
229
    g_free(nodename);
230
}
231

232
static void fdt_add_flash_node(LoongArchVirtMachineState *lvms)
233
{
234
    MachineState *ms = MACHINE(lvms);
235
    char *nodename;
236
    MemoryRegion *flash_mem;
237

238
    hwaddr flash0_base;
239
    hwaddr flash0_size;
240

241
    hwaddr flash1_base;
242
    hwaddr flash1_size;
243

244
    flash_mem = pflash_cfi01_get_memory(lvms->flash[0]);
245
    flash0_base = flash_mem->addr;
246
    flash0_size = memory_region_size(flash_mem);
247

248
    flash_mem = pflash_cfi01_get_memory(lvms->flash[1]);
249
    flash1_base = flash_mem->addr;
250
    flash1_size = memory_region_size(flash_mem);
251

252
    nodename = g_strdup_printf("/flash@%" PRIx64, flash0_base);
253
    qemu_fdt_add_subnode(ms->fdt, nodename);
254
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
255
    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
256
                                 2, flash0_base, 2, flash0_size,
257
                                 2, flash1_base, 2, flash1_size);
258
    qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
259
    g_free(nodename);
260
}
261

262
static void fdt_add_rtc_node(LoongArchVirtMachineState *lvms,
263
                             uint32_t *pch_pic_phandle)
264
{
265
    char *nodename;
266
    hwaddr base = VIRT_RTC_REG_BASE;
267
    hwaddr size = VIRT_RTC_LEN;
268
    MachineState *ms = MACHINE(lvms);
269

270
    nodename = g_strdup_printf("/rtc@%" PRIx64, base);
271
    qemu_fdt_add_subnode(ms->fdt, nodename);
272
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
273
                            "loongson,ls7a-rtc");
274
    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
275
    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
276
                           VIRT_RTC_IRQ - VIRT_GSI_BASE , 0x4);
277
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
278
                          *pch_pic_phandle);
279
    g_free(nodename);
280
}
281

282
static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
283
                              uint32_t *pch_pic_phandle)
284
{
285
    char *nodename;
286
    hwaddr base = VIRT_UART_BASE;
287
    hwaddr size = VIRT_UART_SIZE;
288
    MachineState *ms = MACHINE(lvms);
289

290
    nodename = g_strdup_printf("/serial@%" PRIx64, base);
291
    qemu_fdt_add_subnode(ms->fdt, nodename);
292
    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "ns16550a");
293
    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0, base, 0x0, size);
294
    qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000);
295
    qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
296
    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
297
                           VIRT_UART_IRQ - VIRT_GSI_BASE, 0x4);
298
    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
299
                          *pch_pic_phandle);
300
    g_free(nodename);
301
}
302

303
static void create_fdt(LoongArchVirtMachineState *lvms)
304
{
305
    MachineState *ms = MACHINE(lvms);
306

307
    ms->fdt = create_device_tree(&lvms->fdt_size);
308
    if (!ms->fdt) {
309
        error_report("create_device_tree() failed");
310
        exit(1);
311
    }
312

313
    /* Header */
314
    qemu_fdt_setprop_string(ms->fdt, "/", "compatible",
315
                            "linux,dummy-loongson3");
316
    qemu_fdt_setprop_cell(ms->fdt, "/", "#address-cells", 0x2);
317
    qemu_fdt_setprop_cell(ms->fdt, "/", "#size-cells", 0x2);
318
    qemu_fdt_add_subnode(ms->fdt, "/chosen");
319
}
320

321
static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms)
322
{
323
    int num;
324
    const MachineState *ms = MACHINE(lvms);
325
    int smp_cpus = ms->smp.cpus;
326

327
    qemu_fdt_add_subnode(ms->fdt, "/cpus");
328
    qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1);
329
    qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
330

331
    /* cpu nodes */
332
    for (num = smp_cpus - 1; num >= 0; num--) {
333
        char *nodename = g_strdup_printf("/cpus/cpu@%d", num);
334
        LoongArchCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num));
335
        CPUState *cs = CPU(cpu);
336

337
        qemu_fdt_add_subnode(ms->fdt, nodename);
338
        qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
339
        qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
340
                                cpu->dtb_compatible);
341
        if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
342
            qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id",
343
                ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
344
        }
345
        qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num);
346
        qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
347
                              qemu_fdt_alloc_phandle(ms->fdt));
348
        g_free(nodename);
349
    }
350

351
    /*cpu map */
352
    qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map");
353

354
    for (num = smp_cpus - 1; num >= 0; num--) {
355
        char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num);
356
        char *map_path;
357

358
        if (ms->smp.threads > 1) {
359
            map_path = g_strdup_printf(
360
                "/cpus/cpu-map/socket%d/core%d/thread%d",
361
                num / (ms->smp.cores * ms->smp.threads),
362
                (num / ms->smp.threads) % ms->smp.cores,
363
                num % ms->smp.threads);
364
        } else {
365
            map_path = g_strdup_printf(
366
                "/cpus/cpu-map/socket%d/core%d",
367
                num / ms->smp.cores,
368
                num % ms->smp.cores);
369
        }
370
        qemu_fdt_add_path(ms->fdt, map_path);
371
        qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", cpu_path);
372

373
        g_free(map_path);
374
        g_free(cpu_path);
375
    }
376
}
377

378
static void fdt_add_fw_cfg_node(const LoongArchVirtMachineState *lvms)
379
{
380
    char *nodename;
381
    hwaddr base = VIRT_FWCFG_BASE;
382
    const MachineState *ms = MACHINE(lvms);
383

384
    nodename = g_strdup_printf("/fw_cfg@%" PRIx64, base);
385
    qemu_fdt_add_subnode(ms->fdt, nodename);
386
    qemu_fdt_setprop_string(ms->fdt, nodename,
387
                            "compatible", "qemu,fw-cfg-mmio");
388
    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
389
                                 2, base, 2, 0x18);
390
    qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
391
    g_free(nodename);
392
}
393

394
static void fdt_add_pcie_irq_map_node(const LoongArchVirtMachineState *lvms,
395
                                      char *nodename,
396
                                      uint32_t *pch_pic_phandle)
397
{
398
    int pin, dev;
399
    uint32_t irq_map_stride = 0;
400
    uint32_t full_irq_map[GPEX_NUM_IRQS *GPEX_NUM_IRQS * 10] = {};
401
    uint32_t *irq_map = full_irq_map;
402
    const MachineState *ms = MACHINE(lvms);
403

404
    /* This code creates a standard swizzle of interrupts such that
405
     * each device's first interrupt is based on it's PCI_SLOT number.
406
     * (See pci_swizzle_map_irq_fn())
407
     *
408
     * We only need one entry per interrupt in the table (not one per
409
     * possible slot) seeing the interrupt-map-mask will allow the table
410
     * to wrap to any number of devices.
411
     */
412

413
    for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
414
        int devfn = dev * 0x8;
415

416
        for (pin = 0; pin  < GPEX_NUM_IRQS; pin++) {
417
            int irq_nr = 16 + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
418
            int i = 0;
419

420
            /* Fill PCI address cells */
421
            irq_map[i] = cpu_to_be32(devfn << 8);
422
            i += 3;
423

424
            /* Fill PCI Interrupt cells */
425
            irq_map[i] = cpu_to_be32(pin + 1);
426
            i += 1;
427

428
            /* Fill interrupt controller phandle and cells */
429
            irq_map[i++] = cpu_to_be32(*pch_pic_phandle);
430
            irq_map[i++] = cpu_to_be32(irq_nr);
431

432
            if (!irq_map_stride) {
433
                irq_map_stride = i;
434
            }
435
            irq_map += irq_map_stride;
436
        }
437
    }
438

439

440
    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-map", full_irq_map,
441
                     GPEX_NUM_IRQS * GPEX_NUM_IRQS *
442
                     irq_map_stride * sizeof(uint32_t));
443
    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-map-mask",
444
                     0x1800, 0, 0, 0x7);
445
}
446

447
static void fdt_add_pcie_node(const LoongArchVirtMachineState *lvms,
448
                              uint32_t *pch_pic_phandle,
449
                              uint32_t *pch_msi_phandle)
450
{
451
    char *nodename;
452
    hwaddr base_mmio = VIRT_PCI_MEM_BASE;
453
    hwaddr size_mmio = VIRT_PCI_MEM_SIZE;
454
    hwaddr base_pio = VIRT_PCI_IO_BASE;
455
    hwaddr size_pio = VIRT_PCI_IO_SIZE;
456
    hwaddr base_pcie = VIRT_PCI_CFG_BASE;
457
    hwaddr size_pcie = VIRT_PCI_CFG_SIZE;
458
    hwaddr base = base_pcie;
459

460
    const MachineState *ms = MACHINE(lvms);
461

462
    nodename = g_strdup_printf("/pcie@%" PRIx64, base);
463
    qemu_fdt_add_subnode(ms->fdt, nodename);
464
    qemu_fdt_setprop_string(ms->fdt, nodename,
465
                            "compatible", "pci-host-ecam-generic");
466
    qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "pci");
467
    qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 3);
468
    qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 2);
469
    qemu_fdt_setprop_cell(ms->fdt, nodename, "linux,pci-domain", 0);
470
    qemu_fdt_setprop_cells(ms->fdt, nodename, "bus-range", 0,
471
                           PCIE_MMCFG_BUS(VIRT_PCI_CFG_SIZE - 1));
472
    qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
473
    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
474
                                 2, base_pcie, 2, size_pcie);
475
    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "ranges",
476
                                 1, FDT_PCI_RANGE_IOPORT, 2, VIRT_PCI_IO_OFFSET,
477
                                 2, base_pio, 2, size_pio,
478
                                 1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
479
                                 2, base_mmio, 2, size_mmio);
480
    qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-map",
481
                           0, *pch_msi_phandle, 0, 0x10000);
482

483
    fdt_add_pcie_irq_map_node(lvms, nodename, pch_pic_phandle);
484

485
    g_free(nodename);
486
}
487

488
static void fdt_add_memory_node(MachineState *ms,
489
                                uint64_t base, uint64_t size, int node_id)
490
{
491
    char *nodename = g_strdup_printf("/memory@%" PRIx64, base);
492

493
    qemu_fdt_add_subnode(ms->fdt, nodename);
494
    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base,
495
                           size >> 32, size);
496
    qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
497

498
    if (ms->numa_state && ms->numa_state->num_nodes) {
499
        qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id", node_id);
500
    }
501

502
    g_free(nodename);
503
}
504

505
static void fdt_add_memory_nodes(MachineState *ms)
506
{
507
    hwaddr base, size, ram_size, gap;
508
    int i, nb_numa_nodes, nodes;
509
    NodeInfo *numa_info;
510

511
    ram_size = ms->ram_size;
512
    base = VIRT_LOWMEM_BASE;
513
    gap = VIRT_LOWMEM_SIZE;
514
    nodes = nb_numa_nodes = ms->numa_state->num_nodes;
515
    numa_info = ms->numa_state->nodes;
516
    if (!nodes) {
517
        nodes = 1;
518
    }
519

520
    for (i = 0; i < nodes; i++) {
521
        if (nb_numa_nodes) {
522
            size = numa_info[i].node_mem;
523
        } else {
524
            size = ram_size;
525
        }
526

527
        /*
528
         * memory for the node splited into two part
529
         *   lowram:  [base, +gap)
530
         *   highram: [VIRT_HIGHMEM_BASE, +(len - gap))
531
         */
532
        if (size >= gap) {
533
            fdt_add_memory_node(ms, base, gap, i);
534
            size -= gap;
535
            base = VIRT_HIGHMEM_BASE;
536
            gap = ram_size - VIRT_LOWMEM_SIZE;
537
        }
538

539
        if (size) {
540
            fdt_add_memory_node(ms, base, size, i);
541
            base += size;
542
            gap -= size;
543
        }
544
    }
545
}
546

547
static void virt_build_smbios(LoongArchVirtMachineState *lvms)
548
{
549
    MachineState *ms = MACHINE(lvms);
550
    MachineClass *mc = MACHINE_GET_CLASS(lvms);
551
    uint8_t *smbios_tables, *smbios_anchor;
552
    size_t smbios_tables_len, smbios_anchor_len;
553
    const char *product = "QEMU Virtual Machine";
554

555
    if (!lvms->fw_cfg) {
556
        return;
557
    }
558

559
    smbios_set_defaults("QEMU", product, mc->name);
560

561
    smbios_get_tables(ms, SMBIOS_ENTRY_POINT_TYPE_64,
562
                      NULL, 0,
563
                      &smbios_tables, &smbios_tables_len,
564
                      &smbios_anchor, &smbios_anchor_len, &error_fatal);
565

566
    if (smbios_anchor) {
567
        fw_cfg_add_file(lvms->fw_cfg, "etc/smbios/smbios-tables",
568
                        smbios_tables, smbios_tables_len);
569
        fw_cfg_add_file(lvms->fw_cfg, "etc/smbios/smbios-anchor",
570
                        smbios_anchor, smbios_anchor_len);
571
    }
572
}
573

574
static void virt_done(Notifier *notifier, void *data)
575
{
576
    LoongArchVirtMachineState *lvms = container_of(notifier,
577
                                      LoongArchVirtMachineState, machine_done);
578
    virt_build_smbios(lvms);
579
    loongarch_acpi_setup(lvms);
580
}
581

582
static void virt_powerdown_req(Notifier *notifier, void *opaque)
583
{
584
    LoongArchVirtMachineState *s;
585

586
    s = container_of(notifier, LoongArchVirtMachineState, powerdown_notifier);
587
    acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS);
588
}
589

590
static void memmap_add_entry(uint64_t address, uint64_t length, uint32_t type)
591
{
592
    /* Ensure there are no duplicate entries. */
593
    for (unsigned i = 0; i < memmap_entries; i++) {
594
        assert(memmap_table[i].address != address);
595
    }
596

597
    memmap_table = g_renew(struct memmap_entry, memmap_table,
598
                           memmap_entries + 1);
599
    memmap_table[memmap_entries].address = cpu_to_le64(address);
600
    memmap_table[memmap_entries].length = cpu_to_le64(length);
601
    memmap_table[memmap_entries].type = cpu_to_le32(type);
602
    memmap_table[memmap_entries].reserved = 0;
603
    memmap_entries++;
604
}
605

606
static DeviceState *create_acpi_ged(DeviceState *pch_pic,
607
                                    LoongArchVirtMachineState *lvms)
608
{
609
    DeviceState *dev;
610
    MachineState *ms = MACHINE(lvms);
611
    uint32_t event = ACPI_GED_PWR_DOWN_EVT;
612

613
    if (ms->ram_slots) {
614
        event |= ACPI_GED_MEM_HOTPLUG_EVT;
615
    }
616
    dev = qdev_new(TYPE_ACPI_GED);
617
    qdev_prop_set_uint32(dev, "ged-event", event);
618
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
619

620
    /* ged event */
621
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, VIRT_GED_EVT_ADDR);
622
    /* memory hotplug */
623
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, VIRT_GED_MEM_ADDR);
624
    /* ged regs used for reset and power down */
625
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);
626

627
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
628
                       qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - VIRT_GSI_BASE));
629
    return dev;
630
}
631

632
static DeviceState *create_platform_bus(DeviceState *pch_pic)
633
{
634
    DeviceState *dev;
635
    SysBusDevice *sysbus;
636
    int i, irq;
637
    MemoryRegion *sysmem = get_system_memory();
638

639
    dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
640
    dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
641
    qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS);
642
    qdev_prop_set_uint32(dev, "mmio_size", VIRT_PLATFORM_BUS_SIZE);
643
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
644

645
    sysbus = SYS_BUS_DEVICE(dev);
646
    for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) {
647
        irq = VIRT_PLATFORM_BUS_IRQ - VIRT_GSI_BASE + i;
648
        sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(pch_pic, irq));
649
    }
650

651
    memory_region_add_subregion(sysmem,
652
                                VIRT_PLATFORM_BUS_BASEADDRESS,
653
                                sysbus_mmio_get_region(sysbus, 0));
654
    return dev;
655
}
656

657
static void virt_devices_init(DeviceState *pch_pic,
658
                                   LoongArchVirtMachineState *lvms,
659
                                   uint32_t *pch_pic_phandle,
660
                                   uint32_t *pch_msi_phandle)
661
{
662
    MachineClass *mc = MACHINE_GET_CLASS(lvms);
663
    DeviceState *gpex_dev;
664
    SysBusDevice *d;
665
    PCIBus *pci_bus;
666
    MemoryRegion *ecam_alias, *ecam_reg, *pio_alias, *pio_reg;
667
    MemoryRegion *mmio_alias, *mmio_reg;
668
    int i;
669

670
    gpex_dev = qdev_new(TYPE_GPEX_HOST);
671
    d = SYS_BUS_DEVICE(gpex_dev);
672
    sysbus_realize_and_unref(d, &error_fatal);
673
    pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus;
674
    lvms->pci_bus = pci_bus;
675

676
    /* Map only part size_ecam bytes of ECAM space */
677
    ecam_alias = g_new0(MemoryRegion, 1);
678
    ecam_reg = sysbus_mmio_get_region(d, 0);
679
    memory_region_init_alias(ecam_alias, OBJECT(gpex_dev), "pcie-ecam",
680
                             ecam_reg, 0, VIRT_PCI_CFG_SIZE);
681
    memory_region_add_subregion(get_system_memory(), VIRT_PCI_CFG_BASE,
682
                                ecam_alias);
683

684
    /* Map PCI mem space */
685
    mmio_alias = g_new0(MemoryRegion, 1);
686
    mmio_reg = sysbus_mmio_get_region(d, 1);
687
    memory_region_init_alias(mmio_alias, OBJECT(gpex_dev), "pcie-mmio",
688
                             mmio_reg, VIRT_PCI_MEM_BASE, VIRT_PCI_MEM_SIZE);
689
    memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE,
690
                                mmio_alias);
691

692
    /* Map PCI IO port space. */
693
    pio_alias = g_new0(MemoryRegion, 1);
694
    pio_reg = sysbus_mmio_get_region(d, 2);
695
    memory_region_init_alias(pio_alias, OBJECT(gpex_dev), "pcie-io", pio_reg,
696
                             VIRT_PCI_IO_OFFSET, VIRT_PCI_IO_SIZE);
697
    memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE,
698
                                pio_alias);
699

700
    for (i = 0; i < GPEX_NUM_IRQS; i++) {
701
        sysbus_connect_irq(d, i,
702
                           qdev_get_gpio_in(pch_pic, 16 + i));
703
        gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
704
    }
705

706
    /* Add pcie node */
707
    fdt_add_pcie_node(lvms, pch_pic_phandle, pch_msi_phandle);
708

709
    serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
710
                   qdev_get_gpio_in(pch_pic,
711
                                    VIRT_UART_IRQ - VIRT_GSI_BASE),
712
                   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
713
    fdt_add_uart_node(lvms, pch_pic_phandle);
714

715
    /* Network init */
716
    pci_init_nic_devices(pci_bus, mc->default_nic);
717

718
    /*
719
     * There are some invalid guest memory access.
720
     * Create some unimplemented devices to emulate this.
721
     */
722
    create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
723
    sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE,
724
                         qdev_get_gpio_in(pch_pic,
725
                         VIRT_RTC_IRQ - VIRT_GSI_BASE));
726
    fdt_add_rtc_node(lvms, pch_pic_phandle);
727

728
    /* acpi ged */
729
    lvms->acpi_ged = create_acpi_ged(pch_pic, lvms);
730
    /* platform bus */
731
    lvms->platform_bus_dev = create_platform_bus(pch_pic);
732
}
733

734
static void virt_irq_init(LoongArchVirtMachineState *lvms)
735
{
736
    MachineState *ms = MACHINE(lvms);
737
    DeviceState *pch_pic, *pch_msi, *cpudev;
738
    DeviceState *ipi, *extioi;
739
    SysBusDevice *d;
740
    LoongArchCPU *lacpu;
741
    CPULoongArchState *env;
742
    CPUState *cpu_state;
743
    int cpu, pin, i, start, num;
744
    uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle;
745

746
    /*
747
     * Extended IRQ model.
748
     *                                 |
749
     * +-----------+     +-------------|--------+     +-----------+
750
     * | IPI/Timer | --> | CPUINTC(0-3)|(4-255) | <-- | IPI/Timer |
751
     * +-----------+     +-------------|--------+     +-----------+
752
     *                         ^       |
753
     *                         |
754
     *                    +---------+
755
     *                    | EIOINTC |
756
     *                    +---------+
757
     *                     ^       ^
758
     *                     |       |
759
     *              +---------+ +---------+
760
     *              | PCH-PIC | | PCH-MSI |
761
     *              +---------+ +---------+
762
     *                ^      ^          ^
763
     *                |      |          |
764
     *         +--------+ +---------+ +---------+
765
     *         | UARTs  | | Devices | | Devices |
766
     *         +--------+ +---------+ +---------+
767
     *
768
     * Virt extended IRQ model.
769
     *
770
     *   +-----+    +---------------+     +-------+
771
     *   | IPI |--> | CPUINTC(0-255)| <-- | Timer |
772
     *   +-----+    +---------------+     +-------+
773
     *                     ^
774
     *                     |
775
     *               +-----------+
776
     *               | V-EIOINTC |
777
     *               +-----------+
778
     *                ^         ^
779
     *                |         |
780
     *         +---------+ +---------+
781
     *         | PCH-PIC | | PCH-MSI |
782
     *         +---------+ +---------+
783
     *           ^      ^          ^
784
     *           |      |          |
785
     *    +--------+ +---------+ +---------+
786
     *    | UARTs  | | Devices | | Devices |
787
     *    +--------+ +---------+ +---------+
788
     */
789

790
    /* Create IPI device */
791
    ipi = qdev_new(TYPE_LOONGARCH_IPI);
792
    qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus);
793
    sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
794

795
    /* IPI iocsr memory region */
796
    memory_region_add_subregion(&lvms->system_iocsr, SMP_IPI_MAILBOX,
797
                   sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
798
    memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
799
                   sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
800

801
    /* Add cpu interrupt-controller */
802
    fdt_add_cpuic_node(lvms, &cpuintc_phandle);
803

804
    for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
805
        cpu_state = qemu_get_cpu(cpu);
806
        cpudev = DEVICE(cpu_state);
807
        lacpu = LOONGARCH_CPU(cpu_state);
808
        env = &(lacpu->env);
809
        env->address_space_iocsr = &lvms->as_iocsr;
810

811
        /* connect ipi irq to cpu irq */
812
        qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
813
        env->ipistate = ipi;
814
    }
815

816
    /* Create EXTIOI device */
817
    extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
818
    qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus);
819
    if (virt_is_veiointc_enabled(lvms)) {
820
        qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
821
    }
822
    sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
823
    memory_region_add_subregion(&lvms->system_iocsr, APIC_BASE,
824
                    sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0));
825
    if (virt_is_veiointc_enabled(lvms)) {
826
        memory_region_add_subregion(&lvms->system_iocsr, EXTIOI_VIRT_BASE,
827
                    sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1));
828
    }
829

830
    /*
831
     * connect ext irq to the cpu irq
832
     * cpu_pin[9:2] <= intc_pin[7:0]
833
     */
834
    for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
835
        cpudev = DEVICE(qemu_get_cpu(cpu));
836
        for (pin = 0; pin < LS3A_INTC_IP; pin++) {
837
            qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
838
                                  qdev_get_gpio_in(cpudev, pin + 2));
839
        }
840
    }
841

842
    /* Add Extend I/O Interrupt Controller node */
843
    fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle);
844

845
    pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
846
    num = VIRT_PCH_PIC_IRQ_NUM;
847
    qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num);
848
    d = SYS_BUS_DEVICE(pch_pic);
849
    sysbus_realize_and_unref(d, &error_fatal);
850
    memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE,
851
                            sysbus_mmio_get_region(d, 0));
852
    memory_region_add_subregion(get_system_memory(),
853
                            VIRT_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
854
                            sysbus_mmio_get_region(d, 1));
855
    memory_region_add_subregion(get_system_memory(),
856
                            VIRT_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
857
                            sysbus_mmio_get_region(d, 2));
858

859
    /* Connect pch_pic irqs to extioi */
860
    for (i = 0; i < num; i++) {
861
        qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
862
    }
863

864
    /* Add PCH PIC node */
865
    fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle);
866

867
    pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
868
    start   =  num;
869
    num = EXTIOI_IRQS - start;
870
    qdev_prop_set_uint32(pch_msi, "msi_irq_base", start);
871
    qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
872
    d = SYS_BUS_DEVICE(pch_msi);
873
    sysbus_realize_and_unref(d, &error_fatal);
874
    sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
875
    for (i = 0; i < num; i++) {
876
        /* Connect pch_msi irqs to extioi */
877
        qdev_connect_gpio_out(DEVICE(d), i,
878
                              qdev_get_gpio_in(extioi, i + start));
879
    }
880

881
    /* Add PCH MSI node */
882
    fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle);
883

884
    virt_devices_init(pch_pic, lvms, &pch_pic_phandle, &pch_msi_phandle);
885
}
886

887
static void virt_firmware_init(LoongArchVirtMachineState *lvms)
888
{
889
    char *filename = MACHINE(lvms)->firmware;
890
    char *bios_name = NULL;
891
    int bios_size, i;
892
    BlockBackend *pflash_blk0;
893
    MemoryRegion *mr;
894

895
    lvms->bios_loaded = false;
896

897
    /* Map legacy -drive if=pflash to machine properties */
898
    for (i = 0; i < ARRAY_SIZE(lvms->flash); i++) {
899
        pflash_cfi01_legacy_drive(lvms->flash[i],
900
                                  drive_get(IF_PFLASH, 0, i));
901
    }
902

903
    virt_flash_map(lvms, get_system_memory());
904

905
    pflash_blk0 = pflash_cfi01_get_blk(lvms->flash[0]);
906

907
    if (pflash_blk0) {
908
        if (filename) {
909
            error_report("cannot use both '-bios' and '-drive if=pflash'"
910
                         "options at once");
911
            exit(1);
912
        }
913
        lvms->bios_loaded = true;
914
        return;
915
    }
916

917
    if (filename) {
918
        bios_name = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename);
919
        if (!bios_name) {
920
            error_report("Could not find ROM image '%s'", filename);
921
            exit(1);
922
        }
923

924
        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(lvms->flash[0]), 0);
925
        bios_size = load_image_mr(bios_name, mr);
926
        if (bios_size < 0) {
927
            error_report("Could not load ROM image '%s'", bios_name);
928
            exit(1);
929
        }
930
        g_free(bios_name);
931
        lvms->bios_loaded = true;
932
    }
933
}
934

935
static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr,
936
                                         uint64_t val, unsigned size,
937
                                         MemTxAttrs attrs)
938
{
939
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque);
940
    uint64_t features;
941

942
    switch (addr) {
943
    case MISC_FUNC_REG:
944
        if (!virt_is_veiointc_enabled(lvms)) {
945
            return MEMTX_OK;
946
        }
947

948
        features = address_space_ldl(&lvms->as_iocsr,
949
                                     EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
950
                                     attrs, NULL);
951
        if (val & BIT_ULL(IOCSRM_EXTIOI_EN)) {
952
            features |= BIT(EXTIOI_ENABLE);
953
        }
954
        if (val & BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE)) {
955
            features |= BIT(EXTIOI_ENABLE_INT_ENCODE);
956
        }
957

958
        address_space_stl(&lvms->as_iocsr,
959
                          EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
960
                          features, attrs, NULL);
961
        break;
962
    default:
963
        g_assert_not_reached();
964
    }
965

966
    return MEMTX_OK;
967
}
968

969
static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
970
                                        uint64_t *data,
971
                                        unsigned size, MemTxAttrs attrs)
972
{
973
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque);
974
    uint64_t ret = 0;
975
    int features;
976

977
    switch (addr) {
978
    case VERSION_REG:
979
        ret = 0x11ULL;
980
        break;
981
    case FEATURE_REG:
982
        ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
983
        if (kvm_enabled()) {
984
            ret |= BIT(IOCSRF_VM);
985
        }
986
        break;
987
    case VENDOR_REG:
988
        ret = 0x6e6f73676e6f6f4cULL; /* "Loongson" */
989
        break;
990
    case CPUNAME_REG:
991
        ret = 0x303030354133ULL;     /* "3A5000" */
992
        break;
993
    case MISC_FUNC_REG:
994
        if (!virt_is_veiointc_enabled(lvms)) {
995
            ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
996
            break;
997
        }
998

999
        features = address_space_ldl(&lvms->as_iocsr,
1000
                                     EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
1001
                                     attrs, NULL);
1002
        if (features & BIT(EXTIOI_ENABLE)) {
1003
            ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
1004
        }
1005
        if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
1006
            ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
1007
        }
1008
        break;
1009
    default:
1010
        g_assert_not_reached();
1011
    }
1012

1013
    *data = ret;
1014
    return MEMTX_OK;
1015
}
1016

1017
static const MemoryRegionOps virt_iocsr_misc_ops = {
1018
    .read_with_attrs  = virt_iocsr_misc_read,
1019
    .write_with_attrs = virt_iocsr_misc_write,
1020
    .endianness = DEVICE_LITTLE_ENDIAN,
1021
    .valid = {
1022
        .min_access_size = 4,
1023
        .max_access_size = 8,
1024
    },
1025
    .impl = {
1026
        .min_access_size = 8,
1027
        .max_access_size = 8,
1028
    },
1029
};
1030

1031
static void fw_cfg_add_memory(MachineState *ms)
1032
{
1033
    hwaddr base, size, ram_size, gap;
1034
    int nb_numa_nodes, nodes;
1035
    NodeInfo *numa_info;
1036

1037
    ram_size = ms->ram_size;
1038
    base = VIRT_LOWMEM_BASE;
1039
    gap = VIRT_LOWMEM_SIZE;
1040
    nodes = nb_numa_nodes = ms->numa_state->num_nodes;
1041
    numa_info = ms->numa_state->nodes;
1042
    if (!nodes) {
1043
        nodes = 1;
1044
    }
1045

1046
    /* add fw_cfg memory map of node0 */
1047
    if (nb_numa_nodes) {
1048
        size = numa_info[0].node_mem;
1049
    } else {
1050
        size = ram_size;
1051
    }
1052

1053
    if (size >= gap) {
1054
        memmap_add_entry(base, gap, 1);
1055
        size -= gap;
1056
        base = VIRT_HIGHMEM_BASE;
1057
    }
1058

1059
    if (size) {
1060
        memmap_add_entry(base, size, 1);
1061
        base += size;
1062
    }
1063

1064
    if (nodes < 2) {
1065
        return;
1066
    }
1067

1068
    /* add fw_cfg memory map of other nodes */
1069
    if (numa_info[0].node_mem < gap && ram_size > gap) {
1070
        /*
1071
         * memory map for the maining nodes splited into two part
1072
         * lowram:  [base, +(gap - numa_info[0].node_mem))
1073
         * highram: [VIRT_HIGHMEM_BASE, +(ram_size - gap))
1074
         */
1075
        memmap_add_entry(base, gap - numa_info[0].node_mem, 1);
1076
        size = ram_size - gap;
1077
        base = VIRT_HIGHMEM_BASE;
1078
    } else {
1079
        size = ram_size - numa_info[0].node_mem;
1080
    }
1081

1082
   if (size)
1083
        memmap_add_entry(base, size, 1);
1084
}
1085

1086
static void virt_init(MachineState *machine)
1087
{
1088
    LoongArchCPU *lacpu;
1089
    const char *cpu_model = machine->cpu_type;
1090
    MemoryRegion *address_space_mem = get_system_memory();
1091
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
1092
    int i;
1093
    hwaddr base, size, ram_size = machine->ram_size;
1094
    const CPUArchIdList *possible_cpus;
1095
    MachineClass *mc = MACHINE_GET_CLASS(machine);
1096
    CPUState *cpu;
1097

1098
    if (!cpu_model) {
1099
        cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
1100
    }
1101

1102
    create_fdt(lvms);
1103

1104
    /* Create IOCSR space */
1105
    memory_region_init_io(&lvms->system_iocsr, OBJECT(machine), NULL,
1106
                          machine, "iocsr", UINT64_MAX);
1107
    address_space_init(&lvms->as_iocsr, &lvms->system_iocsr, "IOCSR");
1108
    memory_region_init_io(&lvms->iocsr_mem, OBJECT(machine),
1109
                          &virt_iocsr_misc_ops,
1110
                          machine, "iocsr_misc", 0x428);
1111
    memory_region_add_subregion(&lvms->system_iocsr, 0, &lvms->iocsr_mem);
1112

1113
    /* Init CPUs */
1114
    possible_cpus = mc->possible_cpu_arch_ids(machine);
1115
    for (i = 0; i < possible_cpus->len; i++) {
1116
        cpu = cpu_create(machine->cpu_type);
1117
        cpu->cpu_index = i;
1118
        machine->possible_cpus->cpus[i].cpu = cpu;
1119
        lacpu = LOONGARCH_CPU(cpu);
1120
        lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
1121
    }
1122
    fdt_add_cpu_nodes(lvms);
1123
    fdt_add_memory_nodes(machine);
1124
    fw_cfg_add_memory(machine);
1125

1126
    /* Node0 memory */
1127
    size = ram_size;
1128
    base = VIRT_LOWMEM_BASE;
1129
    if (size > VIRT_LOWMEM_SIZE) {
1130
        size = VIRT_LOWMEM_SIZE;
1131
    }
1132

1133
    memory_region_init_alias(&lvms->lowmem, NULL, "loongarch.lowram",
1134
                              machine->ram, base, size);
1135
    memory_region_add_subregion(address_space_mem, base, &lvms->lowmem);
1136
    base += size;
1137
    if (ram_size - size) {
1138
        base = VIRT_HIGHMEM_BASE;
1139
        memory_region_init_alias(&lvms->highmem, NULL, "loongarch.highram",
1140
                machine->ram, VIRT_LOWMEM_BASE + size, ram_size - size);
1141
        memory_region_add_subregion(address_space_mem, base, &lvms->highmem);
1142
        base += ram_size - size;
1143
    }
1144

1145
    /* initialize device memory address space */
1146
    if (machine->ram_size < machine->maxram_size) {
1147
        ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
1148

1149
        if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {
1150
            error_report("unsupported amount of memory slots: %"PRIu64,
1151
                         machine->ram_slots);
1152
            exit(EXIT_FAILURE);
1153
        }
1154

1155
        if (QEMU_ALIGN_UP(machine->maxram_size,
1156
                          TARGET_PAGE_SIZE) != machine->maxram_size) {
1157
            error_report("maximum memory size must by aligned to multiple of "
1158
                         "%d bytes", TARGET_PAGE_SIZE);
1159
            exit(EXIT_FAILURE);
1160
        }
1161
        machine_memory_devices_init(machine, base, device_mem_size);
1162
    }
1163

1164
    /* load the BIOS image. */
1165
    virt_firmware_init(lvms);
1166

1167
    /* fw_cfg init */
1168
    lvms->fw_cfg = virt_fw_cfg_init(ram_size, machine);
1169
    rom_set_fw(lvms->fw_cfg);
1170
    if (lvms->fw_cfg != NULL) {
1171
        fw_cfg_add_file(lvms->fw_cfg, "etc/memmap",
1172
                        memmap_table,
1173
                        sizeof(struct memmap_entry) * (memmap_entries));
1174
    }
1175
    fdt_add_fw_cfg_node(lvms);
1176
    fdt_add_flash_node(lvms);
1177

1178
    /* Initialize the IO interrupt subsystem */
1179
    virt_irq_init(lvms);
1180
    platform_bus_add_all_fdt_nodes(machine->fdt, "/platic",
1181
                                   VIRT_PLATFORM_BUS_BASEADDRESS,
1182
                                   VIRT_PLATFORM_BUS_SIZE,
1183
                                   VIRT_PLATFORM_BUS_IRQ);
1184
    lvms->machine_done.notify = virt_done;
1185
    qemu_add_machine_init_done_notifier(&lvms->machine_done);
1186
     /* connect powerdown request */
1187
    lvms->powerdown_notifier.notify = virt_powerdown_req;
1188
    qemu_register_powerdown_notifier(&lvms->powerdown_notifier);
1189

1190
    /*
1191
     * Since lowmem region starts from 0 and Linux kernel legacy start address
1192
     * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
1193
     * access. FDT size limit with 1 MiB.
1194
     * Put the FDT into the memory map as a ROM image: this will ensure
1195
     * the FDT is copied again upon reset, even if addr points into RAM.
1196
     */
1197
    qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
1198
    rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
1199
                          &address_space_memory);
1200
    qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
1201
            rom_ptr_for_as(&address_space_memory, FDT_BASE, lvms->fdt_size));
1202

1203
    lvms->bootinfo.ram_size = ram_size;
1204
    loongarch_load_kernel(machine, &lvms->bootinfo);
1205
}
1206

1207
static void virt_get_acpi(Object *obj, Visitor *v, const char *name,
1208
                          void *opaque, Error **errp)
1209
{
1210
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
1211
    OnOffAuto acpi = lvms->acpi;
1212

1213
    visit_type_OnOffAuto(v, name, &acpi, errp);
1214
}
1215

1216
static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
1217
                               void *opaque, Error **errp)
1218
{
1219
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
1220

1221
    visit_type_OnOffAuto(v, name, &lvms->acpi, errp);
1222
}
1223

1224
static void virt_initfn(Object *obj)
1225
{
1226
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
1227

1228
    if (tcg_enabled()) {
1229
        lvms->veiointc = ON_OFF_AUTO_OFF;
1230
    }
1231
    lvms->acpi = ON_OFF_AUTO_AUTO;
1232
    lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
1233
    lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
1234
    virt_flash_create(lvms);
1235
}
1236

1237
static bool memhp_type_supported(DeviceState *dev)
1238
{
1239
    /* we only support pc dimm now */
1240
    return object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
1241
           !object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
1242
}
1243

1244
static void virt_mem_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
1245
                                 Error **errp)
1246
{
1247
    pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), errp);
1248
}
1249

1250
static void virt_device_pre_plug(HotplugHandler *hotplug_dev,
1251
                                            DeviceState *dev, Error **errp)
1252
{
1253
    if (memhp_type_supported(dev)) {
1254
        virt_mem_pre_plug(hotplug_dev, dev, errp);
1255
    }
1256
}
1257

1258
static void virt_mem_unplug_request(HotplugHandler *hotplug_dev,
1259
                                     DeviceState *dev, Error **errp)
1260
{
1261
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
1262

1263
    /* the acpi ged is always exist */
1264
    hotplug_handler_unplug_request(HOTPLUG_HANDLER(lvms->acpi_ged), dev,
1265
                                   errp);
1266
}
1267

1268
static void virt_device_unplug_request(HotplugHandler *hotplug_dev,
1269
                                          DeviceState *dev, Error **errp)
1270
{
1271
    if (memhp_type_supported(dev)) {
1272
        virt_mem_unplug_request(hotplug_dev, dev, errp);
1273
    }
1274
}
1275

1276
static void virt_mem_unplug(HotplugHandler *hotplug_dev,
1277
                             DeviceState *dev, Error **errp)
1278
{
1279
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
1280

1281
    hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, errp);
1282
    pc_dimm_unplug(PC_DIMM(dev), MACHINE(lvms));
1283
    qdev_unrealize(dev);
1284
}
1285

1286
static void virt_device_unplug(HotplugHandler *hotplug_dev,
1287
                                          DeviceState *dev, Error **errp)
1288
{
1289
    if (memhp_type_supported(dev)) {
1290
        virt_mem_unplug(hotplug_dev, dev, errp);
1291
    }
1292
}
1293

1294
static void virt_mem_plug(HotplugHandler *hotplug_dev,
1295
                             DeviceState *dev, Error **errp)
1296
{
1297
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
1298

1299
    pc_dimm_plug(PC_DIMM(dev), MACHINE(lvms));
1300
    hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged),
1301
                         dev, &error_abort);
1302
}
1303

1304
static void virt_device_plug_cb(HotplugHandler *hotplug_dev,
1305
                                        DeviceState *dev, Error **errp)
1306
{
1307
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
1308
    MachineClass *mc = MACHINE_GET_CLASS(lvms);
1309
    PlatformBusDevice *pbus;
1310

1311
    if (device_is_dynamic_sysbus(mc, dev)) {
1312
        if (lvms->platform_bus_dev) {
1313
            pbus = PLATFORM_BUS_DEVICE(lvms->platform_bus_dev);
1314
            platform_bus_link_device(pbus, SYS_BUS_DEVICE(dev));
1315
        }
1316
    } else if (memhp_type_supported(dev)) {
1317
        virt_mem_plug(hotplug_dev, dev, errp);
1318
    }
1319
}
1320

1321
static HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
1322
                                                DeviceState *dev)
1323
{
1324
    MachineClass *mc = MACHINE_GET_CLASS(machine);
1325

1326
    if (device_is_dynamic_sysbus(mc, dev) ||
1327
        object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
1328
        memhp_type_supported(dev)) {
1329
        return HOTPLUG_HANDLER(machine);
1330
    }
1331
    return NULL;
1332
}
1333

1334
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
1335
{
1336
    int n;
1337
    unsigned int max_cpus = ms->smp.max_cpus;
1338

1339
    if (ms->possible_cpus) {
1340
        assert(ms->possible_cpus->len == max_cpus);
1341
        return ms->possible_cpus;
1342
    }
1343

1344
    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
1345
                                  sizeof(CPUArchId) * max_cpus);
1346
    ms->possible_cpus->len = max_cpus;
1347
    for (n = 0; n < ms->possible_cpus->len; n++) {
1348
        ms->possible_cpus->cpus[n].type = ms->cpu_type;
1349
        ms->possible_cpus->cpus[n].arch_id = n;
1350

1351
        ms->possible_cpus->cpus[n].props.has_socket_id = true;
1352
        ms->possible_cpus->cpus[n].props.socket_id  =
1353
                                   n / (ms->smp.cores * ms->smp.threads);
1354
        ms->possible_cpus->cpus[n].props.has_core_id = true;
1355
        ms->possible_cpus->cpus[n].props.core_id =
1356
                                   n / ms->smp.threads % ms->smp.cores;
1357
        ms->possible_cpus->cpus[n].props.has_thread_id = true;
1358
        ms->possible_cpus->cpus[n].props.thread_id = n % ms->smp.threads;
1359
    }
1360
    return ms->possible_cpus;
1361
}
1362

1363
static CpuInstanceProperties virt_cpu_index_to_props(MachineState *ms,
1364
                                                     unsigned cpu_index)
1365
{
1366
    MachineClass *mc = MACHINE_GET_CLASS(ms);
1367
    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
1368

1369
    assert(cpu_index < possible_cpus->len);
1370
    return possible_cpus->cpus[cpu_index].props;
1371
}
1372

1373
static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
1374
{
1375
    int64_t socket_id;
1376

1377
    if (ms->numa_state->num_nodes) {
1378
        socket_id = ms->possible_cpus->cpus[idx].props.socket_id;
1379
        return socket_id % ms->numa_state->num_nodes;
1380
    } else {
1381
        return 0;
1382
    }
1383
}
1384

1385
static void virt_class_init(ObjectClass *oc, void *data)
1386
{
1387
    MachineClass *mc = MACHINE_CLASS(oc);
1388
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
1389

1390
    mc->init = virt_init;
1391
    mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
1392
    mc->default_ram_id = "loongarch.ram";
1393
    mc->max_cpus = LOONGARCH_MAX_CPUS;
1394
    mc->is_default = 1;
1395
    mc->default_kernel_irqchip_split = false;
1396
    mc->block_default_type = IF_VIRTIO;
1397
    mc->default_boot_order = "c";
1398
    mc->no_cdrom = 1;
1399
    mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
1400
    mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
1401
    mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
1402
    mc->numa_mem_supported = true;
1403
    mc->auto_enable_numa_with_memhp = true;
1404
    mc->auto_enable_numa_with_memdev = true;
1405
    mc->get_hotplug_handler = virt_get_hotplug_handler;
1406
    mc->default_nic = "virtio-net-pci";
1407
    hc->plug = virt_device_plug_cb;
1408
    hc->pre_plug = virt_device_pre_plug;
1409
    hc->unplug_request = virt_device_unplug_request;
1410
    hc->unplug = virt_device_unplug;
1411

1412
    object_class_property_add(oc, "acpi", "OnOffAuto",
1413
        virt_get_acpi, virt_set_acpi,
1414
        NULL, NULL);
1415
    object_class_property_set_description(oc, "acpi",
1416
        "Enable ACPI");
1417
    object_class_property_add(oc, "v-eiointc", "OnOffAuto",
1418
        virt_get_veiointc, virt_set_veiointc,
1419
        NULL, NULL);
1420
    object_class_property_set_description(oc, "v-eiointc",
1421
                            "Enable Virt Extend I/O Interrupt Controller.");
1422
    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
1423
#ifdef CONFIG_TPM
1424
    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
1425
#endif
1426
}
1427

1428
static const TypeInfo virt_machine_types[] = {
1429
    {
1430
        .name           = TYPE_LOONGARCH_VIRT_MACHINE,
1431
        .parent         = TYPE_MACHINE,
1432
        .instance_size  = sizeof(LoongArchVirtMachineState),
1433
        .class_init     = virt_class_init,
1434
        .instance_init  = virt_initfn,
1435
        .interfaces = (InterfaceInfo[]) {
1436
         { TYPE_HOTPLUG_HANDLER },
1437
         { }
1438
        },
1439
    }
1440
};
1441

1442
DEFINE_TYPES(virt_machine_types)
1443

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.