hw/board: promote fdt from ARM VirtMachineState to MachineState

The use of FDT's is quite common across our various platforms. To
allow the guest loader to tweak it we need to make it available in
the generic state. This creates the field and migrates the initial
user to use the generic field. Other boards will be updated in later
patches.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20210303173642.3805-2-alex.bennee@linaro.org>
This commit is contained in:
Alex Bennée 2021-03-03 17:36:36 +00:00
parent 2c9192c177
commit a6487d37c2
3 changed files with 186 additions and 172 deletions

View file

@ -218,14 +218,14 @@ static bool cpu_type_valid(const char *cpu)
return false; return false;
} }
static void create_kaslr_seed(VirtMachineState *vms, const char *node) static void create_kaslr_seed(MachineState *ms, const char *node)
{ {
uint64_t seed; uint64_t seed;
if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) { if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) {
return; return;
} }
qemu_fdt_setprop_u64(vms->fdt, node, "kaslr-seed", seed); qemu_fdt_setprop_u64(ms->fdt, node, "kaslr-seed", seed);
} }
static void create_fdt(VirtMachineState *vms) static void create_fdt(VirtMachineState *vms)
@ -239,7 +239,7 @@ static void create_fdt(VirtMachineState *vms)
exit(1); exit(1);
} }
vms->fdt = fdt; ms->fdt = fdt;
/* Header */ /* Header */
qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt"); qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
@ -248,11 +248,11 @@ static void create_fdt(VirtMachineState *vms)
/* /chosen must exist for load_dtb to fill in necessary properties later */ /* /chosen must exist for load_dtb to fill in necessary properties later */
qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_add_subnode(fdt, "/chosen");
create_kaslr_seed(vms, "/chosen"); create_kaslr_seed(ms, "/chosen");
if (vms->secure) { if (vms->secure) {
qemu_fdt_add_subnode(fdt, "/secure-chosen"); qemu_fdt_add_subnode(fdt, "/secure-chosen");
create_kaslr_seed(vms, "/secure-chosen"); create_kaslr_seed(ms, "/secure-chosen");
} }
/* Clock node, for the benefit of the UART. The kernel device tree /* Clock node, for the benefit of the UART. The kernel device tree
@ -316,6 +316,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
ARMCPU *armcpu; ARMCPU *armcpu;
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
MachineState *ms = MACHINE(vms);
if (vmc->claim_edge_triggered_timers) { if (vmc->claim_edge_triggered_timers) {
irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
@ -327,19 +328,19 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
(1 << MACHINE(vms)->smp.cpus) - 1); (1 << MACHINE(vms)->smp.cpus) - 1);
} }
qemu_fdt_add_subnode(vms->fdt, "/timer"); qemu_fdt_add_subnode(ms->fdt, "/timer");
armcpu = ARM_CPU(qemu_get_cpu(0)); armcpu = ARM_CPU(qemu_get_cpu(0));
if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
const char compat[] = "arm,armv8-timer\0arm,armv7-timer"; const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
qemu_fdt_setprop(vms->fdt, "/timer", "compatible", qemu_fdt_setprop(ms->fdt, "/timer", "compatible",
compat, sizeof(compat)); compat, sizeof(compat));
} else { } else {
qemu_fdt_setprop_string(vms->fdt, "/timer", "compatible", qemu_fdt_setprop_string(ms->fdt, "/timer", "compatible",
"arm,armv7-timer"); "arm,armv7-timer");
} }
qemu_fdt_setprop(vms->fdt, "/timer", "always-on", NULL, 0); qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
qemu_fdt_setprop_cells(vms->fdt, "/timer", "interrupts", qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
@ -375,35 +376,35 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
} }
} }
qemu_fdt_add_subnode(vms->fdt, "/cpus"); qemu_fdt_add_subnode(ms->fdt, "/cpus");
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells); qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
for (cpu = smp_cpus - 1; cpu >= 0; cpu--) { for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
CPUState *cs = CPU(armcpu); CPUState *cs = CPU(armcpu);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu"); qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
armcpu->dtb_compatible); armcpu->dtb_compatible);
if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED && smp_cpus > 1) { if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED && smp_cpus > 1) {
qemu_fdt_setprop_string(vms->fdt, nodename, qemu_fdt_setprop_string(ms->fdt, nodename,
"enable-method", "psci"); "enable-method", "psci");
} }
if (addr_cells == 2) { if (addr_cells == 2) {
qemu_fdt_setprop_u64(vms->fdt, nodename, "reg", qemu_fdt_setprop_u64(ms->fdt, nodename, "reg",
armcpu->mp_affinity); armcpu->mp_affinity);
} else { } else {
qemu_fdt_setprop_cell(vms->fdt, nodename, "reg", qemu_fdt_setprop_cell(ms->fdt, nodename, "reg",
armcpu->mp_affinity); armcpu->mp_affinity);
} }
if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id",
ms->possible_cpus->cpus[cs->cpu_index].props.node_id); ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
} }
@ -414,71 +415,74 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
static void fdt_add_its_gic_node(VirtMachineState *vms) static void fdt_add_its_gic_node(VirtMachineState *vms)
{ {
char *nodename; char *nodename;
MachineState *ms = MACHINE(vms);
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt); vms->msi_phandle = qemu_fdt_alloc_phandle(ms->fdt);
nodename = g_strdup_printf("/intc/its@%" PRIx64, nodename = g_strdup_printf("/intc/its@%" PRIx64,
vms->memmap[VIRT_GIC_ITS].base); vms->memmap[VIRT_GIC_ITS].base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,gic-v3-its"); "arm,gic-v3-its");
qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_ITS].base, 2, vms->memmap[VIRT_GIC_ITS].base,
2, vms->memmap[VIRT_GIC_ITS].size); 2, vms->memmap[VIRT_GIC_ITS].size);
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", vms->msi_phandle);
g_free(nodename); g_free(nodename);
} }
static void fdt_add_v2m_gic_node(VirtMachineState *vms) static void fdt_add_v2m_gic_node(VirtMachineState *vms)
{ {
MachineState *ms = MACHINE(vms);
char *nodename; char *nodename;
nodename = g_strdup_printf("/intc/v2m@%" PRIx64, nodename = g_strdup_printf("/intc/v2m@%" PRIx64,
vms->memmap[VIRT_GIC_V2M].base); vms->memmap[VIRT_GIC_V2M].base);
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt); vms->msi_phandle = qemu_fdt_alloc_phandle(ms->fdt);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,gic-v2m-frame"); "arm,gic-v2m-frame");
qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_V2M].base, 2, vms->memmap[VIRT_GIC_V2M].base,
2, vms->memmap[VIRT_GIC_V2M].size); 2, vms->memmap[VIRT_GIC_V2M].size);
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", vms->msi_phandle);
g_free(nodename); g_free(nodename);
} }
static void fdt_add_gic_node(VirtMachineState *vms) static void fdt_add_gic_node(VirtMachineState *vms)
{ {
MachineState *ms = MACHINE(vms);
char *nodename; char *nodename;
vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt); vms->gic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle); qemu_fdt_setprop_cell(ms->fdt, "/", "interrupt-parent", vms->gic_phandle);
nodename = g_strdup_printf("/intc@%" PRIx64, nodename = g_strdup_printf("/intc@%" PRIx64,
vms->memmap[VIRT_GIC_DIST].base); vms->memmap[VIRT_GIC_DIST].base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 3); qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 3);
qemu_fdt_setprop(vms->fdt, nodename, "interrupt-controller", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2); qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2); qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2);
qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0);
if (vms->gic_version == VIRT_GIC_VERSION_3) { if (vms->gic_version == VIRT_GIC_VERSION_3) {
int nb_redist_regions = virt_gicv3_redist_region_count(vms); int nb_redist_regions = virt_gicv3_redist_region_count(vms);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,gic-v3"); "arm,gic-v3");
qemu_fdt_setprop_cell(vms->fdt, nodename, qemu_fdt_setprop_cell(ms->fdt, nodename,
"#redistributor-regions", nb_redist_regions); "#redistributor-regions", nb_redist_regions);
if (nb_redist_regions == 1) { if (nb_redist_regions == 1) {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base, 2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size, 2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_REDIST].base, 2, vms->memmap[VIRT_GIC_REDIST].base,
2, vms->memmap[VIRT_GIC_REDIST].size); 2, vms->memmap[VIRT_GIC_REDIST].size);
} else { } else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base, 2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size, 2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_REDIST].base, 2, vms->memmap[VIRT_GIC_REDIST].base,
@ -488,22 +492,22 @@ static void fdt_add_gic_node(VirtMachineState *vms)
} }
if (vms->virt) { if (vms->virt) {
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ, GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
} }
} else { } else {
/* 'cortex-a15-gic' means 'GIC v2' */ /* 'cortex-a15-gic' means 'GIC v2' */
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,cortex-a15-gic"); "arm,cortex-a15-gic");
if (!vms->virt) { if (!vms->virt) {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base, 2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size, 2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base, 2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size); 2, vms->memmap[VIRT_GIC_CPU].size);
} else { } else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base, 2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size, 2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base, 2, vms->memmap[VIRT_GIC_CPU].base,
@ -512,13 +516,13 @@ static void fdt_add_gic_node(VirtMachineState *vms)
2, vms->memmap[VIRT_GIC_HYP].size, 2, vms->memmap[VIRT_GIC_HYP].size,
2, vms->memmap[VIRT_GIC_VCPU].base, 2, vms->memmap[VIRT_GIC_VCPU].base,
2, vms->memmap[VIRT_GIC_VCPU].size); 2, vms->memmap[VIRT_GIC_VCPU].size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ, GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
} }
} }
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", vms->gic_phandle);
g_free(nodename); g_free(nodename);
} }
@ -526,6 +530,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
{ {
ARMCPU *armcpu = ARM_CPU(first_cpu); ARMCPU *armcpu = ARM_CPU(first_cpu);
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
MachineState *ms = MACHINE(vms);
if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
assert(!object_property_get_bool(OBJECT(armcpu), "pmu", NULL)); assert(!object_property_get_bool(OBJECT(armcpu), "pmu", NULL));
@ -538,12 +543,12 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
(1 << MACHINE(vms)->smp.cpus) - 1); (1 << MACHINE(vms)->smp.cpus) - 1);
} }
qemu_fdt_add_subnode(vms->fdt, "/pmu"); qemu_fdt_add_subnode(ms->fdt, "/pmu");
if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
const char compat[] = "arm,armv8-pmuv3"; const char compat[] = "arm,armv8-pmuv3";
qemu_fdt_setprop(vms->fdt, "/pmu", "compatible", qemu_fdt_setprop(ms->fdt, "/pmu", "compatible",
compat, sizeof(compat)); compat, sizeof(compat));
qemu_fdt_setprop_cells(vms->fdt, "/pmu", "interrupts", qemu_fdt_setprop_cells(ms->fdt, "/pmu", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags); GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags);
} }
} }
@ -749,6 +754,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
const char clocknames[] = "uartclk\0apb_pclk"; const char clocknames[] = "uartclk\0apb_pclk";
DeviceState *dev = qdev_new(TYPE_PL011); DeviceState *dev = qdev_new(TYPE_PL011);
SysBusDevice *s = SYS_BUS_DEVICE(dev); SysBusDevice *s = SYS_BUS_DEVICE(dev);
MachineState *ms = MACHINE(vms);
qdev_prop_set_chr(dev, "chardev", chr); qdev_prop_set_chr(dev, "chardev", chr);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
@ -757,28 +763,28 @@ static void create_uart(const VirtMachineState *vms, int uart,
sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/pl011@%" PRIx64, base); nodename = g_strdup_printf("/pl011@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
/* Note that we can't use setprop_string because of the embedded NUL */ /* Note that we can't use setprop_string because of the embedded NUL */
qemu_fdt_setprop(vms->fdt, nodename, "compatible", qemu_fdt_setprop(ms->fdt, nodename, "compatible",
compat, sizeof(compat)); compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size); 2, base, 2, size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cells(vms->fdt, nodename, "clocks", qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks",
vms->clock_phandle, vms->clock_phandle); vms->clock_phandle, vms->clock_phandle);
qemu_fdt_setprop(vms->fdt, nodename, "clock-names", qemu_fdt_setprop(ms->fdt, nodename, "clock-names",
clocknames, sizeof(clocknames)); clocknames, sizeof(clocknames));
if (uart == VIRT_UART) { if (uart == VIRT_UART) {
qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
} else { } else {
/* Mark as not usable by the normal world */ /* Mark as not usable by the normal world */
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
qemu_fdt_setprop_string(vms->fdt, "/secure-chosen", "stdout-path", qemu_fdt_setprop_string(ms->fdt, "/secure-chosen", "stdout-path",
nodename); nodename);
} }
@ -792,19 +798,20 @@ static void create_rtc(const VirtMachineState *vms)
hwaddr size = vms->memmap[VIRT_RTC].size; hwaddr size = vms->memmap[VIRT_RTC].size;
int irq = vms->irqmap[VIRT_RTC]; int irq = vms->irqmap[VIRT_RTC];
const char compat[] = "arm,pl031\0arm,primecell"; const char compat[] = "arm,pl031\0arm,primecell";
MachineState *ms = MACHINE(vms);
sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq)); sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/pl031@%" PRIx64, base); nodename = g_strdup_printf("/pl031@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat)); qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size); 2, base, 2, size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk"); qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
g_free(nodename); g_free(nodename);
} }
@ -821,32 +828,30 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
} }
} }
static void create_gpio_keys(const VirtMachineState *vms, static void create_gpio_keys(char *fdt, DeviceState *pl061_dev,
DeviceState *pl061_dev,
uint32_t phandle) uint32_t phandle)
{ {
gpio_key_dev = sysbus_create_simple("gpio-key", -1, gpio_key_dev = sysbus_create_simple("gpio-key", -1,
qdev_get_gpio_in(pl061_dev, 3)); qdev_get_gpio_in(pl061_dev, 3));
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys"); qemu_fdt_add_subnode(fdt, "/gpio-keys");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys"); qemu_fdt_setprop_string(fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0); qemu_fdt_setprop_cell(fdt, "/gpio-keys", "#size-cells", 0);
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1); qemu_fdt_setprop_cell(fdt, "/gpio-keys", "#address-cells", 1);
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff"); qemu_fdt_add_subnode(fdt, "/gpio-keys/poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff", qemu_fdt_setprop_string(fdt, "/gpio-keys/poweroff",
"label", "GPIO Key Poweroff"); "label", "GPIO Key Poweroff");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code", qemu_fdt_setprop_cell(fdt, "/gpio-keys/poweroff", "linux,code",
KEY_POWER); KEY_POWER);
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", qemu_fdt_setprop_cells(fdt, "/gpio-keys/poweroff",
"gpios", phandle, 3, 0); "gpios", phandle, 3, 0);
} }
#define SECURE_GPIO_POWEROFF 0 #define SECURE_GPIO_POWEROFF 0
#define SECURE_GPIO_RESET 1 #define SECURE_GPIO_RESET 1
static void create_secure_gpio_pwr(const VirtMachineState *vms, static void create_secure_gpio_pwr(char *fdt, DeviceState *pl061_dev,
DeviceState *pl061_dev,
uint32_t phandle) uint32_t phandle)
{ {
DeviceState *gpio_pwr_dev; DeviceState *gpio_pwr_dev;
@ -860,22 +865,22 @@ static void create_secure_gpio_pwr(const VirtMachineState *vms,
qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF, qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0)); qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff"); qemu_fdt_add_subnode(fdt, "/gpio-poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible", qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "compatible",
"gpio-poweroff"); "gpio-poweroff");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff", qemu_fdt_setprop_cells(fdt, "/gpio-poweroff",
"gpios", phandle, SECURE_GPIO_POWEROFF, 0); "gpios", phandle, SECURE_GPIO_POWEROFF, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled"); qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status", qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "secure-status",
"okay"); "okay");
qemu_fdt_add_subnode(vms->fdt, "/gpio-restart"); qemu_fdt_add_subnode(fdt, "/gpio-restart");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible", qemu_fdt_setprop_string(fdt, "/gpio-restart", "compatible",
"gpio-restart"); "gpio-restart");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart", qemu_fdt_setprop_cells(fdt, "/gpio-restart",
"gpios", phandle, SECURE_GPIO_RESET, 0); "gpios", phandle, SECURE_GPIO_RESET, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled"); qemu_fdt_setprop_string(fdt, "/gpio-restart", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status", qemu_fdt_setprop_string(fdt, "/gpio-restart", "secure-status",
"okay"); "okay");
} }
@ -889,6 +894,7 @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
int irq = vms->irqmap[gpio]; int irq = vms->irqmap[gpio];
const char compat[] = "arm,pl061\0arm,primecell"; const char compat[] = "arm,pl061\0arm,primecell";
SysBusDevice *s; SysBusDevice *s;
MachineState *ms = MACHINE(vms);
pl061_dev = qdev_new("pl061"); pl061_dev = qdev_new("pl061");
s = SYS_BUS_DEVICE(pl061_dev); s = SYS_BUS_DEVICE(pl061_dev);
@ -896,33 +902,33 @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt); uint32_t phandle = qemu_fdt_alloc_phandle(ms->fdt);
nodename = g_strdup_printf("/pl061@%" PRIx64, base); nodename = g_strdup_printf("/pl061@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size); 2, base, 2, size);
qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat)); qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_cell(vms->fdt, nodename, "#gpio-cells", 2); qemu_fdt_setprop_cell(ms->fdt, nodename, "#gpio-cells", 2);
qemu_fdt_setprop(vms->fdt, nodename, "gpio-controller", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "gpio-controller", NULL, 0);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk"); qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle); qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", phandle);
if (gpio != VIRT_GPIO) { if (gpio != VIRT_GPIO) {
/* Mark as not usable by the normal world */ /* Mark as not usable by the normal world */
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
} }
g_free(nodename); g_free(nodename);
/* Child gpio devices */ /* Child gpio devices */
if (gpio == VIRT_GPIO) { if (gpio == VIRT_GPIO) {
create_gpio_keys(vms, pl061_dev, phandle); create_gpio_keys(ms->fdt, pl061_dev, phandle);
} else { } else {
create_secure_gpio_pwr(vms, pl061_dev, phandle); create_secure_gpio_pwr(ms->fdt, pl061_dev, phandle);
} }
} }
@ -930,6 +936,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
{ {
int i; int i;
hwaddr size = vms->memmap[VIRT_MMIO].size; hwaddr size = vms->memmap[VIRT_MMIO].size;
MachineState *ms = MACHINE(vms);
/* We create the transports in forwards order. Since qbus_realize() /* We create the transports in forwards order. Since qbus_realize()
* prepends (not appends) new child buses, the incrementing loop below will * prepends (not appends) new child buses, the incrementing loop below will
@ -979,15 +986,15 @@ static void create_virtio_devices(const VirtMachineState *vms)
hwaddr base = vms->memmap[VIRT_MMIO].base + i * size; hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base); nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, qemu_fdt_setprop_string(ms->fdt, nodename,
"compatible", "virtio,mmio"); "compatible", "virtio,mmio");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size); 2, base, 2, size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
g_free(nodename); g_free(nodename);
} }
} }
@ -1068,17 +1075,18 @@ static void virt_flash_fdt(VirtMachineState *vms,
{ {
hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2; hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
hwaddr flashbase = vms->memmap[VIRT_FLASH].base; hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
MachineState *ms = MACHINE(vms);
char *nodename; char *nodename;
if (sysmem == secure_sysmem) { if (sysmem == secure_sysmem) {
/* Report both flash devices as a single node in the DT */ /* Report both flash devices as a single node in the DT */
nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, flashbase, 2, flashsize, 2, flashbase, 2, flashsize,
2, flashbase + flashsize, 2, flashsize); 2, flashbase + flashsize, 2, flashsize);
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
g_free(nodename); g_free(nodename);
} else { } else {
/* /*
@ -1086,21 +1094,21 @@ static void virt_flash_fdt(VirtMachineState *vms,
* only visible to the secure world. * only visible to the secure world.
*/ */
nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase); nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, flashbase, 2, flashsize); 2, flashbase, 2, flashsize);
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
g_free(nodename); g_free(nodename);
nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, flashbase + flashsize, 2, flashsize); 2, flashbase + flashsize, 2, flashsize);
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
g_free(nodename); g_free(nodename);
} }
} }
@ -1167,17 +1175,17 @@ static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base); nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, qemu_fdt_setprop_string(ms->fdt, nodename,
"compatible", "qemu,fw-cfg-mmio"); "compatible", "qemu,fw-cfg-mmio");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size); 2, base, 2, size);
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
g_free(nodename); g_free(nodename);
return fw_cfg; return fw_cfg;
} }
static void create_pcie_irq_map(const VirtMachineState *vms, static void create_pcie_irq_map(const MachineState *ms,
uint32_t gic_phandle, uint32_t gic_phandle,
int first_irq, const char *nodename) int first_irq, const char *nodename)
{ {
@ -1205,10 +1213,10 @@ static void create_pcie_irq_map(const VirtMachineState *vms,
} }
} }
qemu_fdt_setprop(vms->fdt, nodename, "interrupt-map", qemu_fdt_setprop(ms->fdt, nodename, "interrupt-map",
full_irq_map, sizeof(full_irq_map)); full_irq_map, sizeof(full_irq_map));
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupt-map-mask", qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-map-mask",
cpu_to_be16(PCI_DEVFN(3, 0)), /* Slot 3 */ cpu_to_be16(PCI_DEVFN(3, 0)), /* Slot 3 */
0, 0, 0, 0,
0x7 /* PCI irq */); 0x7 /* PCI irq */);
@ -1225,6 +1233,7 @@ static void create_smmu(const VirtMachineState *vms,
hwaddr size = vms->memmap[VIRT_SMMU].size; hwaddr size = vms->memmap[VIRT_SMMU].size;
const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror"; const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
DeviceState *dev; DeviceState *dev;
MachineState *ms = MACHINE(vms);
if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) { if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
return; return;
@ -1242,26 +1251,26 @@ static void create_smmu(const VirtMachineState *vms,
} }
node = g_strdup_printf("/smmuv3@%" PRIx64, base); node = g_strdup_printf("/smmuv3@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, node); qemu_fdt_add_subnode(ms->fdt, node);
qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat)); qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size); qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg", 2, base, 2, size);
qemu_fdt_setprop_cells(vms->fdt, node, "interrupts", qemu_fdt_setprop_cells(ms->fdt, node, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names, qemu_fdt_setprop(ms->fdt, node, "interrupt-names", irq_names,
sizeof(irq_names)); sizeof(irq_names));
qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle); qemu_fdt_setprop_cell(ms->fdt, node, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk"); qemu_fdt_setprop_string(ms->fdt, node, "clock-names", "apb_pclk");
qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0); qemu_fdt_setprop(ms->fdt, node, "dma-coherent", NULL, 0);
qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1); qemu_fdt_setprop_cell(ms->fdt, node, "#iommu-cells", 1);
qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle); qemu_fdt_setprop_cell(ms->fdt, node, "phandle", vms->iommu_phandle);
g_free(node); g_free(node);
} }
@ -1269,22 +1278,23 @@ static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
{ {
const char compat[] = "virtio,pci-iommu"; const char compat[] = "virtio,pci-iommu";
uint16_t bdf = vms->virtio_iommu_bdf; uint16_t bdf = vms->virtio_iommu_bdf;
MachineState *ms = MACHINE(vms);
char *node; char *node;
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt); vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
node = g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, bdf); node = g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, bdf);
qemu_fdt_add_subnode(vms->fdt, node); qemu_fdt_add_subnode(ms->fdt, node);
qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat)); qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg",
1, bdf << 8, 1, 0, 1, 0, 1, bdf << 8, 1, 0, 1, 0,
1, 0, 1, 0); 1, 0, 1, 0);
qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1); qemu_fdt_setprop_cell(ms->fdt, node, "#iommu-cells", 1);
qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle); qemu_fdt_setprop_cell(ms->fdt, node, "phandle", vms->iommu_phandle);
g_free(node); g_free(node);
qemu_fdt_setprop_cells(vms->fdt, vms->pciehb_nodename, "iommu-map", qemu_fdt_setprop_cells(ms->fdt, vms->pciehb_nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, bdf, 0x0, vms->iommu_phandle, 0x0, bdf,
bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - bdf); bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - bdf);
} }
@ -1309,6 +1319,7 @@ static void create_pcie(VirtMachineState *vms)
char *nodename; char *nodename;
int i, ecam_id; int i, ecam_id;
PCIHostState *pci; PCIHostState *pci;
MachineState *ms = MACHINE(vms);
dev = qdev_new(TYPE_GPEX_HOST); dev = qdev_new(TYPE_GPEX_HOST);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
@ -1369,27 +1380,27 @@ static void create_pcie(VirtMachineState *vms)
} }
nodename = vms->pciehb_nodename = g_strdup_printf("/pcie@%" PRIx64, base); nodename = vms->pciehb_nodename = g_strdup_printf("/pcie@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, qemu_fdt_setprop_string(ms->fdt, nodename,
"compatible", "pci-host-ecam-generic"); "compatible", "pci-host-ecam-generic");
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci"); qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "pci");
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3); qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 3);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2); qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 2);
qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0); qemu_fdt_setprop_cell(ms->fdt, nodename, "linux,pci-domain", 0);
qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0, qemu_fdt_setprop_cells(ms->fdt, nodename, "bus-range", 0,
nr_pcie_buses - 1); nr_pcie_buses - 1);
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
if (vms->msi_phandle) { if (vms->msi_phandle) {
qemu_fdt_setprop_cells(vms->fdt, nodename, "msi-parent", qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-parent",
vms->msi_phandle); vms->msi_phandle);
} }
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base_ecam, 2, size_ecam); 2, base_ecam, 2, size_ecam);
if (vms->highmem) { if (vms->highmem) {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0, 1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_pio, 2, size_pio, 2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
@ -1398,23 +1409,23 @@ static void create_pcie(VirtMachineState *vms)
2, base_mmio_high, 2, base_mmio_high,
2, base_mmio_high, 2, size_mmio_high); 2, base_mmio_high, 2, size_mmio_high);
} else { } else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges", qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0, 1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_pio, 2, size_pio, 2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio); 2, base_mmio, 2, size_mmio);
} }
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1); qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename); create_pcie_irq_map(ms, vms->gic_phandle, irq, nodename);
if (vms->iommu) { if (vms->iommu) {
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt); vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
switch (vms->iommu) { switch (vms->iommu) {
case VIRT_IOMMU_SMMUV3: case VIRT_IOMMU_SMMUV3:
create_smmu(vms, vms->bus); create_smmu(vms, vms->bus);
qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", qemu_fdt_setprop_cells(ms->fdt, nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, 0x10000); 0x0, vms->iommu_phandle, 0x0, 0x10000);
break; break;
default: default:
@ -1466,17 +1477,18 @@ static void create_secure_ram(VirtMachineState *vms,
char *nodename; char *nodename;
hwaddr base = vms->memmap[VIRT_SECURE_MEM].base; hwaddr base = vms->memmap[VIRT_SECURE_MEM].base;
hwaddr size = vms->memmap[VIRT_SECURE_MEM].size; hwaddr size = vms->memmap[VIRT_SECURE_MEM].size;
MachineState *ms = MACHINE(vms);
memory_region_init_ram(secram, NULL, "virt.secure-ram", size, memory_region_init_ram(secram, NULL, "virt.secure-ram", size,
&error_fatal); &error_fatal);
memory_region_add_subregion(secure_sysmem, base, secram); memory_region_add_subregion(secure_sysmem, base, secram);
nodename = g_strdup_printf("/secram@%" PRIx64, base); nodename = g_strdup_printf("/secram@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "memory"); qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
if (secure_tag_sysmem) { if (secure_tag_sysmem) {
create_tag_ram(secure_tag_sysmem, base, size, "mach-virt.secure-tag"); create_tag_ram(secure_tag_sysmem, base, size, "mach-virt.secure-tag");
@ -1489,9 +1501,11 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
{ {
const VirtMachineState *board = container_of(binfo, VirtMachineState, const VirtMachineState *board = container_of(binfo, VirtMachineState,
bootinfo); bootinfo);
MachineState *ms = MACHINE(board);
*fdt_size = board->fdt_size; *fdt_size = board->fdt_size;
return board->fdt; return ms->fdt;
} }
static void virt_build_smbios(VirtMachineState *vms) static void virt_build_smbios(VirtMachineState *vms)
@ -1539,7 +1553,7 @@ void virt_machine_done(Notifier *notifier, void *data)
* while qemu takes charge of the qom stuff. * while qemu takes charge of the qom stuff.
*/ */
if (info->dtb_filename == NULL) { if (info->dtb_filename == NULL) {
platform_bus_add_all_fdt_nodes(vms->fdt, "/intc", platform_bus_add_all_fdt_nodes(ms->fdt, "/intc",
vms->memmap[VIRT_PLATFORM_BUS].base, vms->memmap[VIRT_PLATFORM_BUS].base,
vms->memmap[VIRT_PLATFORM_BUS].size, vms->memmap[VIRT_PLATFORM_BUS].size,
vms->irqmap[VIRT_PLATFORM_BUS]); vms->irqmap[VIRT_PLATFORM_BUS]);

View file

@ -153,7 +153,6 @@ struct VirtMachineState {
MemMapEntry *memmap; MemMapEntry *memmap;
char *pciehb_nodename; char *pciehb_nodename;
const int *irqmap; const int *irqmap;
void *fdt;
int fdt_size; int fdt_size;
uint32_t clock_phandle; uint32_t clock_phandle;
uint32_t gic_phandle; uint32_t gic_phandle;

View file

@ -258,6 +258,7 @@ struct MachineState {
/*< public >*/ /*< public >*/
void *fdt;
char *dtb; char *dtb;
char *dumpdtb; char *dumpdtb;
int phandle_start; int phandle_start;