All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/2] Add mach-virt platform
@ 2013-05-10  6:58 John Rigby
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob John Rigby
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: John Rigby @ 2013-05-10  6:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, John Rigby

Modify arm fdt handling so boards can provide a blob
rather than requiring one on command line.

Allow dumping of fdt blob as ppc e500 already does.

Next add mach-virt platform that creates fdt blob from scratch
describing its minimal hw which is a pl011 uart and a sp804 timer.

Tested on amd64 host with full system emulation and also using kvm
on an arndale board

v2 changes:
- remove bogus cruft from mach-virt.c that was leftover
  from checkpatch fixing

v3 changes:
- split first patch into two
- rename from mach-virt to virt
- collect scattered constants into a machine info structure
- put qemu device creation and fdt nod creation near one another to make
  it easier to keep them in sync
- use CONFIG_KVM and kvm_enabled() to differentiate between tcg and kvm
  dependent code
- move memory to 0x0 and io up to 0xfff00000

John Rigby (3):
  ARM: Allow boards to provide an fdt blob
  ARM: Allow dumping of device tree
  ARM: Add mach-virt platform

 hw/arm/Makefile.objs |   2 +-
 hw/arm/boot.c        |  31 ++--
 hw/arm/virt.c        | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/arm.h |   6 +
 4 files changed, 461 insertions(+), 12 deletions(-)
 create mode 100644 hw/arm/virt.c

-- 
1.8.2.2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob
  2013-05-10  6:58 [Qemu-devel] [PATCH v3 0/2] Add mach-virt platform John Rigby
@ 2013-05-10  6:58 ` John Rigby
  2013-06-13 18:49   ` Peter Maydell
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree John Rigby
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 3/3] ARM: Add mach-virt platform John Rigby
  2 siblings, 1 reply; 6+ messages in thread
From: John Rigby @ 2013-05-10  6:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, John Rigby

If no fdt is provided on command line and the new field
get_dtb in struct arm_boot_info is set then call it to
get a device tree blob.

Signed-off-by: John Rigby <john.rigby@linaro.org>
---

changes in v3:
- split patch

 hw/arm/boot.c        | 30 +++++++++++++++++++-----------
 include/hw/arm/arm.h |  6 ++++++
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index f451529..64b56ac 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -235,19 +235,27 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
     int size, rc;
     uint32_t acells, scells, hival;
 
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
-    if (!filename) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
-        return -1;
-    }
+    if (binfo->dtb_filename) {
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+        if (!filename) {
+            fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
+            return -1;
+        }
 
-    fdt = load_device_tree(filename, &size);
-    if (!fdt) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+        fdt = load_device_tree(filename, &size);
+        if (!fdt) {
+            fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+            g_free(filename);
+            return -1;
+        }
         g_free(filename);
-        return -1;
+    } else if (binfo->get_dtb) {
+        fdt = binfo->get_dtb(addr, binfo, &size);
+        if (!fdt) {
+            fprintf(stderr, "Couldn't get dtb blob from board func\n");
+            return -1;
+        }
     }
-    g_free(filename);
 
     acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
     scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
@@ -440,7 +448,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
         /* for device tree boot, we pass the DTB directly in r2. Otherwise
          * we point to the kernel args.
          */
-        if (info->dtb_filename) {
+        if (info->dtb_filename || info->get_dtb) {
             /* Place the DTB after the initrd in memory. Note that some
              * kernels will trash anything in the 4K page the initrd
              * ends in, so make sure the DTB isn't caught up in that.
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 7b2b02d..4c56a1b 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -31,6 +31,10 @@ struct arm_boot_info {
     const char *kernel_cmdline;
     const char *initrd_filename;
     const char *dtb_filename;
+    /* if a board is able to create a dtb without a dtb file then it
+     * sets get_dtb.  This will only be used if no dtb file is provided.
+     */
+    void *(*get_dtb)(hwaddr addr, const struct arm_boot_info *binfo, int *size);
     hwaddr loader_start;
     /* multicore boards that use the default secondary core boot functions
      * need to put the address of the secondary boot code, the boot reg,
@@ -59,6 +63,8 @@ struct arm_boot_info {
     int is_linux;
     hwaddr initrd_start;
     hwaddr initrd_size;
+    void *dtb_blob;
+    int dtb_blob_size;
     hwaddr entry;
 };
 void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree
  2013-05-10  6:58 [Qemu-devel] [PATCH v3 0/2] Add mach-virt platform John Rigby
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob John Rigby
@ 2013-05-10  6:58 ` John Rigby
  2013-06-13 17:53   ` Peter Maydell
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 3/3] ARM: Add mach-virt platform John Rigby
  2 siblings, 1 reply; 6+ messages in thread
From: John Rigby @ 2013-05-10  6:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, John Rigby

By calling qemu_devtree_dumpdtb near the end of load_dtb.

Signed-off-by: John Rigby <john.rigby@linaro.org>
---

changes in v3:
- split patch

 hw/arm/boot.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 64b56ac..de71edf 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -312,6 +312,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
         }
     }
+    qemu_devtree_dumpdtb(fdt, size);
 
     cpu_physical_memory_write(addr, fdt, size);
 
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v3 3/3] ARM: Add mach-virt platform
  2013-05-10  6:58 [Qemu-devel] [PATCH v3 0/2] Add mach-virt platform John Rigby
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob John Rigby
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree John Rigby
@ 2013-05-10  6:58 ` John Rigby
  2 siblings, 0 replies; 6+ messages in thread
From: John Rigby @ 2013-05-10  6:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, John Rigby

Add mach-virt platform support corresponding to
/arch/arm/mach-virt in kernel tree.

For now it is not virtual but instantiates a pl011 uart
and an sp804 timer.  The uart is need for a console
the timer is needed when running without kvm and there
is no arch timer.

Signed-off-by: John Rigby <john.rigby@linaro.org>
---

changes in v2:
- remove bogus cruft from mach-virt.c that was leftwover from checkpatch fixing

changes in v3:
- rename from mach-virt to virt
- collect scattered constants into a machine info structure
- put qemu device creation and fdt node creation near one another to make
  it easier to keep them in sync
- use CONFIG_KVM and kvm_enabled() to differentiate between tcg and kvm
  dependent code
- move memory to 0x0 and io up to 0xfff00000

 hw/arm/Makefile.objs |   2 +-
 hw/arm/virt.c        | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 435 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/virt.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9e3a06f..744484f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,7 +1,7 @@
 obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
 obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
 obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
-obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
+obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o strongarm.o
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
new file mode 100644
index 0000000..22e3510
--- /dev/null
+++ b/hw/arm/virt.c
@@ -0,0 +1,434 @@
+/*
+ * ARM mach-virt emulation
+ *
+ * Copyright (c) 2013 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Emulate a virtual board compatible with arch/arm/mach-virt/virt.c in the linux
+ * kernel source.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm/arm.h"
+#include "hw/arm/primecell.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+#include "libfdt_env.h"
+
+#define GIC_FDT_IRQ_NUM_CELLS 3
+
+#define GIC_FDT_IRQ_TYPE_SPI 0
+#define GIC_FDT_IRQ_TYPE_PPI 1
+
+#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
+#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
+#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
+#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
+
+#define GIC_FDT_IRQ_PPI_CPU_SHIFT 8
+#define GIC_FDT_IRQ_PPI_CPU_MASK (0xff << GIC_FDT_IRQ_PPI_CPU_SHIFT)
+
+#define CPU_NAME_MAX_LEN 16
+
+#define MEM_BASE 0
+#define MAX_MEM 0xff800000
+#define IO_BASE 0xfff00000
+#define IO_LEN 0x000f0000
+
+struct machine_info {
+    const char cpu_model[CPU_NAME_MAX_LEN];
+    const char *cpu_compat;
+    const char *qdevname;
+    uint64_t mem_base;
+    uint64_t max_mem;
+    uint64_t io_base;
+    uint64_t io_len;
+    /* offsets and sizes of gic regions */
+    struct {
+        uint32_t dist_base;
+        uint32_t dist_size;
+        uint32_t cpui_base;
+        uint32_t cpui_size;
+        uint32_t total_size;
+        const char *compatible;
+    } gic_info;
+    char *gic;
+};
+
+static struct machine_info machines[] = {
+    {
+        .cpu_model = "cortex-a15",
+        .cpu_compat = "arm,cortex-a15",
+        .qdevname = "a15mpcore_priv",
+        .mem_base = MEM_BASE,
+        .max_mem = MAX_MEM,
+        .io_base = IO_BASE,
+        .io_len = IO_LEN,
+        .gic_info = {0x01000, 0x1000, 0x02000, 0x1000, 0x8000, "arm,cortex-a15-gic"},
+    },
+    {
+        .cpu_model = "cortex-a9",
+        .cpu_compat = "arm,cortex-a9",
+        .qdevname = "a9mpcore_priv",
+        .mem_base = MEM_BASE,
+        .max_mem = MAX_MEM,
+        .io_base = IO_BASE,
+        .io_len = IO_LEN,
+        .gic_info = {0x01000, 0x1000, 0x0100, 0x0100, 0x2000, "arm,cortex-a9-gic"},
+    },
+    {
+        .cpu_model = "",
+    },
+};
+
+static struct machine_info *find_machine_info(const char *cpu)
+{
+    struct machine_info *mi = machines;
+
+    while (mi->cpu_model) {
+        if (strncmp(cpu, mi->cpu_model, sizeof(mi->cpu_model)) == 0) {
+            return mi;
+        }
+        mi++;
+    }
+    return NULL;
+}
+
+static void *virt_fdt;
+static int virt_fdt_size;
+
+static void *initial_fdt(struct machine_info *mi)
+{
+    void *fdt = create_device_tree(&virt_fdt_size);
+    char compatible_sb[] = "simple-bus\0arm,amba-bus";
+
+    if (fdt == NULL) {
+        return NULL;
+    }
+
+    /* Header */
+    qemu_devtree_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
+    qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 0x2);
+    qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 0x2);
+
+    /*
+     * /chosen and /memory nodes must exist for load_dtb
+     * to fill in neccessary properties later
+     */
+    qemu_devtree_add_subnode(fdt, "/chosen");
+    qemu_devtree_add_subnode(fdt, "/memory");
+    qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
+
+    /*
+     * Fixed soc properties
+     */
+    qemu_devtree_add_subnode(fdt, "/soc");
+    qemu_devtree_setprop(fdt, "/soc", "compatible", compatible_sb,
+            sizeof(compatible_sb));
+    qemu_devtree_setprop_cell(fdt, "/soc", "#address-cells", 0x1);
+    qemu_devtree_setprop_cell(fdt, "/soc", "#size-cells", 0x1);
+    qemu_devtree_setprop_cells(fdt, "/soc", "ranges", mi->io_base, 0x0,
+            mi->io_base, mi->io_len);
+    qemu_devtree_setprop_cell(fdt, "/soc", "#interrupt-cells", 0x1);
+
+    /* No PSCI for TCG yet */
+#ifdef CONFIG_KVM
+    if (kvm_enabled()) {
+        qemu_devtree_add_subnode(fdt, "/psci");
+        qemu_devtree_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+        qemu_devtree_setprop_string(fdt, "/psci", "method", "hvc");
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_suspend",
+                KVM_PSCI_FN_CPU_SUSPEND);
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_off", KVM_PSCI_FN_CPU_OFF);
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_on", KVM_PSCI_FN_CPU_ON);
+        qemu_devtree_setprop_cell(fdt, "/psci", "migrate", KVM_PSCI_FN_MIGRATE);
+    }
+#endif
+    return  fdt;
+}
+
+static void fdt_add_timer_nodes(void *fdt, int smp_cpus)
+{
+    uint32_t cpu_mask =
+        (((1 << smp_cpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT)
+                        & GIC_FDT_IRQ_PPI_CPU_MASK;
+    cpu_mask = 0xf00;
+    uint32_t irq_prop[] = {
+        cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+        cpu_to_fdt32(13),
+        cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+        cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+        cpu_to_fdt32(14),
+        cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+        cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+        cpu_to_fdt32(11),
+        cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+        cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+        cpu_to_fdt32(10),
+        cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+    };
+
+    qemu_devtree_add_subnode(fdt, "/timer");
+    qemu_devtree_setprop_string(fdt, "/timer", "compatible", "arm,armv7-timer");
+    qemu_devtree_setprop(fdt, "/timer", "interrupts", irq_prop,
+            sizeof(irq_prop));
+}
+
+static void fdt_add_cpu_nodes(void *fdt, int smp_cpus)
+{
+    int cpu;
+
+    qemu_devtree_add_subnode(fdt, "/cpus");
+    qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
+    qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
+
+    for (cpu = 0; cpu < smp_cpus; ++cpu) {
+        char cpu_name[CPU_NAME_MAX_LEN];
+
+        snprintf(cpu_name, CPU_NAME_MAX_LEN, "/cpus/cpu@%d", cpu);
+
+        qemu_devtree_add_subnode(fdt, cpu_name);
+        qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
+        qemu_devtree_setprop_string(fdt, cpu_name, "compatible",
+            "arm,cortex-a15");
+
+        if (smp_cpus > 1) {
+            qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "psci");
+        }
+
+        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu);
+    }
+}
+
+static void add_interrupt_map(void *fdt, const char *soc, uint32_t gic, int nirqs)
+{
+    int i, irq;
+    int len;
+    uint32_t *map;
+
+    qemu_devtree_setprop_cell(fdt, soc, "#interrupt-cells", 0x1);
+    qemu_devtree_setprop_cells(fdt, soc, "interrupt-map-mask", 0, 63);
+
+    len = nirqs * 6 * sizeof(uint32_t);
+    map = g_malloc(len);
+
+    for (i = 0, irq = 0; irq < nirqs; irq++) {
+        map[i++] = cpu_to_be32(0x0);
+        map[i++] = cpu_to_be32(irq);
+        map[i++] = cpu_to_be32(gic);
+        map[i++] = cpu_to_be32(0x0);
+        map[i++] = cpu_to_be32(irq);
+        map[i++] = cpu_to_be32(4);
+    }
+    qemu_devtree_setprop(fdt, soc, "interrupt-map", map, len);
+    g_free(map);
+}
+
+static void fdt_add_gic_node(void *fdt, struct machine_info *mi)
+{
+    uint32_t gic_phandle;
+    uint64_t reg_prop[4];
+
+    reg_prop[0] = cpu_to_fdt64(mi->gic_info.dist_base + mi->io_base);
+    reg_prop[1] = cpu_to_fdt64(mi->gic_info.dist_size);
+    reg_prop[2] = cpu_to_fdt64(mi->gic_info.cpui_base + mi->io_base);
+    reg_prop[3] = cpu_to_fdt64(mi->gic_info.cpui_size);
+
+    mi->io_base += mi->gic_info.total_size;
+
+    gic_phandle = qemu_devtree_alloc_phandle(fdt);
+    qemu_devtree_setprop_cell(fdt, "/", "interrupt-parent", gic_phandle);
+
+    qemu_devtree_add_subnode(fdt, "/intc");
+    qemu_devtree_setprop_string(fdt, "/intc", "compatible",
+            mi->gic_info.compatible);
+    qemu_devtree_setprop_cell(fdt, "/intc", "#interrupt-cells",
+            GIC_FDT_IRQ_NUM_CELLS);
+    qemu_devtree_setprop(fdt, "/intc", "interrupt-controller", NULL, 0);
+    qemu_devtree_setprop(fdt, "/intc", "reg", reg_prop, sizeof(reg_prop));
+    qemu_devtree_setprop_cell(fdt, "/intc", "phandle", gic_phandle);
+    add_interrupt_map(fdt, "/soc", gic_phandle, 43);
+}
+
+static void fdt_add_soc_nodes(void *fdt, struct machine_info *mi, qemu_irq *pic)
+{
+    uint32_t clock_phandle;
+    char compatible_uart[] = "arm,pl011\0arm,primecell";
+    char compatible_timer[] = "arm,sp804\0arm,primecell";
+    char clock_names_uart[] = "uartclk\0apb_pclk";
+    char clock_names_timer[] = "timerclk\0apb_pclk";
+    uint32_t base;
+    uint32_t len;
+    int irq;
+
+    clock_phandle = qemu_devtree_alloc_phandle(fdt);
+    qemu_devtree_add_subnode(fdt, "/soc/clock");
+    qemu_devtree_setprop_string(fdt, "/soc/clock", "compatible", "fixed-clock");
+    qemu_devtree_setprop_cell(fdt, "/soc/clock", "#clock-cells", 0x0);
+    qemu_devtree_setprop_cell(fdt, "/soc/clock", "clock-frequency", 24000000);
+    qemu_devtree_setprop_string(fdt, "/soc/clock", "clock-output-names",
+            "clk24mhz");
+    qemu_devtree_setprop_cell(fdt, "/soc/clock", "phandle", clock_phandle);
+
+    len = 0x1000;
+    base = mi->io_base;
+    mi->io_base += len;
+    irq = 5;
+    sysbus_create_simple("pl011", base, pic[irq]);
+    qemu_devtree_add_subnode(fdt, "/soc/uart");
+    qemu_devtree_setprop(fdt, "/soc/uart", "compatible", compatible_uart,
+            sizeof(compatible_uart));
+    qemu_devtree_setprop_cells(fdt, "/soc/uart", "reg", base, len);
+    qemu_devtree_setprop_cell(fdt, "/soc/uart", "interrupts", irq);
+    qemu_devtree_setprop_cells(fdt, "/soc/uart", "clocks", clock_phandle,
+            clock_phandle);
+    qemu_devtree_setprop(fdt, "/soc/uart", "clock-names", clock_names_uart,
+            sizeof(clock_names_uart));
+
+    len = 0x1000;
+    base = mi->io_base;
+    mi->io_base += len;
+    irq = 2;
+    sysbus_create_simple("sp804", base, pic[irq]);
+    qemu_devtree_add_subnode(fdt, "/soc/timer");
+    qemu_devtree_setprop(fdt, "/soc/timer", "compatible", compatible_timer,
+            sizeof(compatible_timer));
+    qemu_devtree_setprop_cells(fdt, "/soc/timer", "reg", base, len);
+    qemu_devtree_setprop_cell(fdt, "/soc/timer", "interrupts", irq);
+    qemu_devtree_setprop_cells(fdt, "/soc/timer", "clocks", clock_phandle,
+            clock_phandle);
+    qemu_devtree_setprop(fdt, "/soc/timer", "clock-names", clock_names_timer,
+            sizeof(clock_names_timer));
+}
+
+static void *machvirt_dtb(hwaddr addr, const struct arm_boot_info *binfo,
+        int *fdt_size)
+{
+    *fdt_size = virt_fdt_size;
+    return virt_fdt;
+}
+
+static struct arm_boot_info machvirt_binfo;
+
+static void machvirt_init(QEMUMachineInitArgs *args)
+{
+    qemu_irq pic[64];
+    MemoryRegion *sysmem = get_system_memory();
+    int n;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    qemu_irq cpu_irq[4];
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    const char *cpu_model = args->cpu_model;
+    struct machine_info *mi;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a15";
+    }
+
+    mi = find_machine_info(cpu_model);
+
+    if (!mi) {
+        hw_error("No machine info for cpu%s\n", cpu_model);
+        exit(1);
+    }
+
+    /*
+     * Only supported method of starting secondary CPUs is PSCI and
+     * PSCI is not yet supported with TCG so limit smp_cpus to 1
+     * if not kvm.
+     */
+    if (!kvm_enabled() && smp_cpus > 1) {
+        hw_error("Multiple cpus only supported with kvm\n");
+        exit(1);
+    }
+
+    if (ram_size > mi->max_mem) {
+            fprintf(stderr, "mach-virt: cannot model more than 30GB RAM\n");
+            exit(1);
+    }
+
+    virt_fdt = initial_fdt(mi);
+    fdt_add_timer_nodes(virt_fdt, smp_cpus);
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
+        qemu_irq *irqp;
+
+        cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition %s\n", cpu_model);
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+    fdt_add_cpu_nodes(virt_fdt, smp_cpus);
+
+    memory_region_init_ram(ram, "mach-virt.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(sysmem, mi->mem_base, ram);
+
+    dev = qdev_create(NULL, mi->qdevname);
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, mi->io_base);
+    fdt_add_gic_node(virt_fdt, mi);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /*
+     * Not completely virtual yet, add some soc io nodes
+     */
+    fdt_add_soc_nodes(virt_fdt, mi, pic);
+
+    machvirt_binfo.ram_size = args->ram_size;
+    machvirt_binfo.kernel_filename = args->kernel_filename;
+    machvirt_binfo.kernel_cmdline = args->kernel_cmdline;
+    machvirt_binfo.initrd_filename = args->initrd_filename;
+    machvirt_binfo.nb_cpus = smp_cpus;
+    machvirt_binfo.board_id = -1;
+    machvirt_binfo.loader_start = mi->mem_base;
+    machvirt_binfo.get_dtb = machvirt_dtb;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &machvirt_binfo);
+}
+
+static QEMUMachine machvirt_a15_machine = {
+    .name = "machvirt",
+    .desc = "ARM Virtual Machine",
+    .init = machvirt_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void machvirt_machine_init(void)
+{
+    qemu_register_machine(&machvirt_a15_machine);
+}
+
+machine_init(machvirt_machine_init);
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree John Rigby
@ 2013-06-13 17:53   ` Peter Maydell
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2013-06-13 17:53 UTC (permalink / raw)
  To: John Rigby; +Cc: qemu-devel

On 10 May 2013 07:58, John Rigby <john.rigby@linaro.org> wrote:
> By calling qemu_devtree_dumpdtb near the end of load_dtb.
>
> Signed-off-by: John Rigby <john.rigby@linaro.org>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

I'm just going to put this in arm-devs.next now, since it
makes '-machine dumpdtb=filename' work rather than be
silently ignored.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob
  2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob John Rigby
@ 2013-06-13 18:49   ` Peter Maydell
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2013-06-13 18:49 UTC (permalink / raw)
  To: qemu-devel

(I've taken this work over from John so these review comments
are more in the nature of "notes to myself" than anything else ;-)

On 10 May 2013 07:58, John Rigby <john.rigby@linaro.org> wrote:
> If no fdt is provided on command line and the new field
> get_dtb in struct arm_boot_info is set then call it to
> get a device tree blob.
>
> diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
> index 7b2b02d..4c56a1b 100644
> --- a/include/hw/arm/arm.h
> +++ b/include/hw/arm/arm.h
> @@ -31,6 +31,10 @@ struct arm_boot_info {
>      const char *kernel_cmdline;
>      const char *initrd_filename;
>      const char *dtb_filename;
> +    /* if a board is able to create a dtb without a dtb file then it
> +     * sets get_dtb.  This will only be used if no dtb file is provided.
> +     */
> +    void *(*get_dtb)(hwaddr addr, const struct arm_boot_info *binfo, int *size);

The general idea here is OK, but it's not clear to me why
we need to pass in the addr to the hook function (certainly
the example in part 3 doesn't need it). I think we can just
move to
 void *(*get_dtb)(const struct arm_boot_info *binfo, int *size);

As with load_device_tree(), we should require (and document!)
that the returned blob is in memory freeable with g_free().

NB: we don't actually free the blob in load_dtb(), either
for load_device_tree() or for this; we should (separate patch).

>      hwaddr loader_start;
>      /* multicore boards that use the default secondary core boot functions
>       * need to put the address of the secondary boot code, the boot reg,
> @@ -59,6 +63,8 @@ struct arm_boot_info {
>      int is_linux;
>      hwaddr initrd_start;
>      hwaddr initrd_size;
> +    void *dtb_blob;
> +    int dtb_blob_size;

These appear to be relics from a previous version -- they're not used
and can be dropped.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-06-13 18:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-10  6:58 [Qemu-devel] [PATCH v3 0/2] Add mach-virt platform John Rigby
2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 1/3] ARM: Allow boards to provide an fdt blob John Rigby
2013-06-13 18:49   ` Peter Maydell
2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 2/3] ARM: Allow dumping of device tree John Rigby
2013-06-13 17:53   ` Peter Maydell
2013-05-10  6:58 ` [Qemu-devel] [PATCH v3 3/3] ARM: Add mach-virt platform John Rigby

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.