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;
}
static void create_kaslr_seed(VirtMachineState *vms, const char *node)
static void create_kaslr_seed(MachineState *ms, const char *node)
{
uint64_t seed;
if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) {
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)
@ -239,7 +239,7 @@ static void create_fdt(VirtMachineState *vms)
exit(1);
}
vms->fdt = fdt;
ms->fdt = fdt;
/* Header */
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 */
qemu_fdt_add_subnode(fdt, "/chosen");
create_kaslr_seed(vms, "/chosen");
create_kaslr_seed(ms, "/chosen");
if (vms->secure) {
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
@ -316,6 +316,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
ARMCPU *armcpu;
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
MachineState *ms = MACHINE(vms);
if (vmc->claim_edge_triggered_timers) {
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);
}
qemu_fdt_add_subnode(vms->fdt, "/timer");
qemu_fdt_add_subnode(ms->fdt, "/timer");
armcpu = ARM_CPU(qemu_get_cpu(0));
if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
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));
} else {
qemu_fdt_setprop_string(vms->fdt, "/timer", "compatible",
qemu_fdt_setprop_string(ms->fdt, "/timer", "compatible",
"arm,armv7-timer");
}
qemu_fdt_setprop(vms->fdt, "/timer", "always-on", NULL, 0);
qemu_fdt_setprop_cells(vms->fdt, "/timer", "interrupts",
qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
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_NS_EL1_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_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
qemu_fdt_add_subnode(ms->fdt, "/cpus");
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
CPUState *cs = CPU(armcpu);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu");
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
armcpu->dtb_compatible);
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");
}
if (addr_cells == 2) {
qemu_fdt_setprop_u64(vms->fdt, nodename, "reg",
qemu_fdt_setprop_u64(ms->fdt, nodename, "reg",
armcpu->mp_affinity);
} else {
qemu_fdt_setprop_cell(vms->fdt, nodename, "reg",
qemu_fdt_setprop_cell(ms->fdt, nodename, "reg",
armcpu->mp_affinity);
}
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);
}
@ -414,71 +415,74 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
static void fdt_add_its_gic_node(VirtMachineState *vms)
{
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,
vms->memmap[VIRT_GIC_ITS].base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,gic-v3-its");
qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_setprop(ms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_ITS].base,
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);
}
static void fdt_add_v2m_gic_node(VirtMachineState *vms)
{
MachineState *ms = MACHINE(vms);
char *nodename;
nodename = g_strdup_printf("/intc/v2m@%" PRIx64,
vms->memmap[VIRT_GIC_V2M].base);
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
vms->msi_phandle = qemu_fdt_alloc_phandle(ms->fdt);
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
"arm,gic-v2m-frame");
qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_setprop(ms->fdt, nodename, "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_V2M].base,
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);
}
static void fdt_add_gic_node(VirtMachineState *vms)
{
MachineState *ms = MACHINE(vms);
char *nodename;
vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt);
qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle);
vms->gic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
qemu_fdt_setprop_cell(ms->fdt, "/", "interrupt-parent", vms->gic_phandle);
nodename = g_strdup_printf("/intc@%" PRIx64,
vms->memmap[VIRT_GIC_DIST].base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 3);
qemu_fdt_setprop(vms->fdt, nodename, "interrupt-controller", NULL, 0);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 3);
qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2);
qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2);
qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0);
if (vms->gic_version == VIRT_GIC_VERSION_3) {
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");
qemu_fdt_setprop_cell(vms->fdt, nodename,
qemu_fdt_setprop_cell(ms->fdt, nodename,
"#redistributor-regions", nb_redist_regions);
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].size,
2, vms->memmap[VIRT_GIC_REDIST].base,
2, vms->memmap[VIRT_GIC_REDIST].size);
} 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].size,
2, vms->memmap[VIRT_GIC_REDIST].base,
@ -488,22 +492,22 @@ static void fdt_add_gic_node(VirtMachineState *vms)
}
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_FLAGS_LEVEL_HI);
}
} else {
/* '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");
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].size,
2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size);
} 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].size,
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_VCPU].base,
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_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);
}
@ -526,6 +530,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
{
ARMCPU *armcpu = ARM_CPU(first_cpu);
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
MachineState *ms = MACHINE(vms);
if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
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);
}
qemu_fdt_add_subnode(vms->fdt, "/pmu");
qemu_fdt_add_subnode(ms->fdt, "/pmu");
if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
const char compat[] = "arm,armv8-pmuv3";
qemu_fdt_setprop(vms->fdt, "/pmu", "compatible",
qemu_fdt_setprop(ms->fdt, "/pmu", "compatible",
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);
}
}
@ -749,6 +754,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
const char clocknames[] = "uartclk\0apb_pclk";
DeviceState *dev = qdev_new(TYPE_PL011);
SysBusDevice *s = SYS_BUS_DEVICE(dev);
MachineState *ms = MACHINE(vms);
qdev_prop_set_chr(dev, "chardev", chr);
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));
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 */
qemu_fdt_setprop(vms->fdt, nodename, "compatible",
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);
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_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);
qemu_fdt_setprop(vms->fdt, nodename, "clock-names",
qemu_fdt_setprop(ms->fdt, nodename, "clock-names",
clocknames, sizeof(clocknames));
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 {
/* Mark as not usable by the normal world */
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
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);
}
@ -792,19 +798,20 @@ static void create_rtc(const VirtMachineState *vms)
hwaddr size = vms->memmap[VIRT_RTC].size;
int irq = vms->irqmap[VIRT_RTC];
const char compat[] = "arm,pl031\0arm,primecell";
MachineState *ms = MACHINE(vms);
sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/pl031@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
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_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
g_free(nodename);
}
@ -821,32 +828,30 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
}
}
static void create_gpio_keys(const VirtMachineState *vms,
DeviceState *pl061_dev,
static void create_gpio_keys(char *fdt, DeviceState *pl061_dev,
uint32_t phandle)
{
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
qdev_get_gpio_in(pl061_dev, 3));
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
qemu_fdt_add_subnode(fdt, "/gpio-keys");
qemu_fdt_setprop_string(fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(fdt, "/gpio-keys", "#size-cells", 0);
qemu_fdt_setprop_cell(fdt, "/gpio-keys", "#address-cells", 1);
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
qemu_fdt_add_subnode(fdt, "/gpio-keys/poweroff");
qemu_fdt_setprop_string(fdt, "/gpio-keys/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);
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
qemu_fdt_setprop_cells(fdt, "/gpio-keys/poweroff",
"gpios", phandle, 3, 0);
}
#define SECURE_GPIO_POWEROFF 0
#define SECURE_GPIO_RESET 1
static void create_secure_gpio_pwr(const VirtMachineState *vms,
DeviceState *pl061_dev,
static void create_secure_gpio_pwr(char *fdt, DeviceState *pl061_dev,
uint32_t phandle)
{
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_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
qemu_fdt_add_subnode(fdt, "/gpio-poweroff");
qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "compatible",
"gpio-poweroff");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
qemu_fdt_setprop_cells(fdt, "/gpio-poweroff",
"gpios", phandle, SECURE_GPIO_POWEROFF, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "status", "disabled");
qemu_fdt_setprop_string(fdt, "/gpio-poweroff", "secure-status",
"okay");
qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
qemu_fdt_add_subnode(fdt, "/gpio-restart");
qemu_fdt_setprop_string(fdt, "/gpio-restart", "compatible",
"gpio-restart");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
qemu_fdt_setprop_cells(fdt, "/gpio-restart",
"gpios", phandle, SECURE_GPIO_RESET, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
qemu_fdt_setprop_string(fdt, "/gpio-restart", "status", "disabled");
qemu_fdt_setprop_string(fdt, "/gpio-restart", "secure-status",
"okay");
}
@ -889,6 +894,7 @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
int irq = vms->irqmap[gpio];
const char compat[] = "arm,pl061\0arm,primecell";
SysBusDevice *s;
MachineState *ms = MACHINE(vms);
pl061_dev = qdev_new("pl061");
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));
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);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, base, 2, size);
qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_cell(vms->fdt, nodename, "#gpio-cells", 2);
qemu_fdt_setprop(vms->fdt, nodename, "gpio-controller", NULL, 0);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_cell(ms->fdt, nodename, "#gpio-cells", 2);
qemu_fdt_setprop(ms->fdt, nodename, "gpio-controller", NULL, 0);
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", phandle);
if (gpio != VIRT_GPIO) {
/* Mark as not usable by the normal world */
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
}
g_free(nodename);
/* Child gpio devices */
if (gpio == VIRT_GPIO) {
create_gpio_keys(vms, pl061_dev, phandle);
create_gpio_keys(ms->fdt, pl061_dev, phandle);
} 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;
hwaddr size = vms->memmap[VIRT_MMIO].size;
MachineState *ms = MACHINE(vms);
/* We create the transports in forwards order. Since qbus_realize()
* 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;
nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename,
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename,
"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);
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_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);
}
}
@ -1068,17 +1075,18 @@ static void virt_flash_fdt(VirtMachineState *vms,
{
hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
MachineState *ms = MACHINE(vms);
char *nodename;
if (sysmem == secure_sysmem) {
/* Report both flash devices as a single node in the DT */
nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, flashbase, 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);
} else {
/*
@ -1086,21 +1094,21 @@ static void virt_flash_fdt(VirtMachineState *vms,
* only visible to the secure world.
*/
nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
2, flashbase, 2, flashsize);
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
g_free(nodename);
nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
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);
}
}
@ -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);
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename,
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename,
"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);
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
g_free(nodename);
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,
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));
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 */
0, 0,
0x7 /* PCI irq */);
@ -1225,6 +1233,7 @@ static void create_smmu(const VirtMachineState *vms,
hwaddr size = vms->memmap[VIRT_SMMU].size;
const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
DeviceState *dev;
MachineState *ms = MACHINE(vms);
if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
return;
@ -1242,26 +1251,26 @@ static void create_smmu(const VirtMachineState *vms,
}
node = g_strdup_printf("/smmuv3@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, node);
qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
qemu_fdt_add_subnode(ms->fdt, node);
qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
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 + 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 + 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));
qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk");
qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0);
qemu_fdt_setprop_cell(ms->fdt, node, "clocks", vms->clock_phandle);
qemu_fdt_setprop_string(ms->fdt, node, "clock-names", "apb_pclk");
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);
}
@ -1269,22 +1278,23 @@ static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
{
const char compat[] = "virtio,pci-iommu";
uint16_t bdf = vms->virtio_iommu_bdf;
MachineState *ms = MACHINE(vms);
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);
qemu_fdt_add_subnode(vms->fdt, node);
qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg",
qemu_fdt_add_subnode(ms->fdt, node);
qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg",
1, bdf << 8, 1, 0, 1, 0,
1, 0, 1, 0);
qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle);
qemu_fdt_setprop_cell(ms->fdt, node, "#iommu-cells", 1);
qemu_fdt_setprop_cell(ms->fdt, node, "phandle", vms->iommu_phandle);
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,
bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - bdf);
}
@ -1309,6 +1319,7 @@ static void create_pcie(VirtMachineState *vms)
char *nodename;
int i, ecam_id;
PCIHostState *pci;
MachineState *ms = MACHINE(vms);
dev = qdev_new(TYPE_GPEX_HOST);
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);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename,
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename,
"compatible", "pci-host-ecam-generic");
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0);
qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "pci");
qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 3);
qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 2);
qemu_fdt_setprop_cell(ms->fdt, nodename, "linux,pci-domain", 0);
qemu_fdt_setprop_cells(ms->fdt, nodename, "bus-range", 0,
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) {
qemu_fdt_setprop_cells(vms->fdt, nodename, "msi-parent",
qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-parent",
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);
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,
2, base_pio, 2, size_pio,
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, size_mmio_high);
} 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,
2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio);
}
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
create_pcie_irq_map(ms, vms->gic_phandle, irq, nodename);
if (vms->iommu) {
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
switch (vms->iommu) {
case VIRT_IOMMU_SMMUV3:
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);
break;
default:
@ -1466,17 +1477,18 @@ static void create_secure_ram(VirtMachineState *vms,
char *nodename;
hwaddr base = vms->memmap[VIRT_SECURE_MEM].base;
hwaddr size = vms->memmap[VIRT_SECURE_MEM].size;
MachineState *ms = MACHINE(vms);
memory_region_init_ram(secram, NULL, "virt.secure-ram", size,
&error_fatal);
memory_region_add_subregion(secure_sysmem, base, secram);
nodename = g_strdup_printf("/secram@%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "memory");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size);
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
if (secure_tag_sysmem) {
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,
bootinfo);
MachineState *ms = MACHINE(board);
*fdt_size = board->fdt_size;
return board->fdt;
return ms->fdt;
}
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.
*/
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].size,
vms->irqmap[VIRT_PLATFORM_BUS]);

View File

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

View File

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