~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu/arm64/0008-hw-arm-Add-virt-platform.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From b206938d22ff59109087a33851e658af7442dba2 Mon Sep 17 00:00:00 2001
 
2
From: Peter Maydell <peter.maydell@linaro.org>
 
3
Date: Fri, 22 Nov 2013 17:17:14 +0000
 
4
Subject: [PATCH 08/49] hw/arm: Add 'virt' platform
 
5
 
 
6
Add 'virt' platform support corresponding to arch/arm/mach-virt
 
7
in the Linux kernel tree. This has no platform-specific code but
 
8
can use any device whose kernel driver is is able to work purely
 
9
from a device tree node. We use this to instantiate a minimal
 
10
set of devices: a GIC and some virtio-mmio transports.
 
11
 
 
12
Signed-off-by: John Rigby <john.rigby@linaro.org>
 
13
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
 
14
Message-id: 1385140638-10444-8-git-send-email-peter.maydell@linaro.org
 
15
[PMM:
 
16
 Significantly overhauled:
 
17
 * renamed user-facing machine to just "virt"
 
18
 * removed the A9 support (it can't work since the A9 has no
 
19
   generic timers)
 
20
 * added virtio-mmio transports instead of random set of 'soc' devices
 
21
   (though we retain a pl011 UART)
 
22
 * instead of updating io_base as we step through adding devices,
 
23
   define a memory map with an array (similar to vexpress)
 
24
 * similarly, define irqmap with an array
 
25
 * folded in some minor fixes from John's aarch64-support patch
 
26
 * rather than explicitly doing endian-swapping on FDT cells,
 
27
   use fdt APIs that let us just pass in host-endian values
 
28
   and let the fdt layer take care of the swapping
 
29
 * miscellaneous minor code cleanups and style fixes
 
30
]
 
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
 
32
---
 
33
 hw/arm/Makefile.objs |   2 +-
 
34
 hw/arm/virt.c        | 444 +++++++++++++++++++++++++++++++++++++++++++++++++++
 
35
 2 files changed, 445 insertions(+), 1 deletion(-)
 
36
 create mode 100644 hw/arm/virt.c
 
37
 
 
38
Index: qemu/hw/arm/Makefile.objs
 
39
===================================================================
 
40
--- qemu.orig/hw/arm/Makefile.objs      2014-01-10 12:03:45.756161023 -0600
 
41
+++ qemu/hw/arm/Makefile.objs   2014-01-10 12:06:39.008164917 -0600
 
42
@@ -1,7 +1,7 @@
 
43
 obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
 
44
 obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
 
45
 obj-y += omap_sx1.o overo.o palm.o realview.o spitz.o stellaris.o
 
46
-obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
47
+obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 
48
 
 
49
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 
50
 obj-y += omap1.o omap2.o omap3.o strongarm.o beagle.o
 
51
Index: qemu/hw/arm/virt.c
 
52
===================================================================
 
53
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
54
+++ qemu/hw/arm/virt.c  2014-01-10 12:03:50.656161133 -0600
 
55
@@ -0,0 +1,444 @@
 
56
+/*
 
57
+ * ARM mach-virt emulation
 
58
+ *
 
59
+ * Copyright (c) 2013 Linaro Limited
 
60
+ *
 
61
+ * This program is free software; you can redistribute it and/or modify it
 
62
+ * under the terms and conditions of the GNU General Public License,
 
63
+ * version 2 or later, as published by the Free Software Foundation.
 
64
+ *
 
65
+ * This program is distributed in the hope it will be useful, but WITHOUT
 
66
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
67
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
68
+ * more details.
 
69
+ *
 
70
+ * You should have received a copy of the GNU General Public License along with
 
71
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
 
72
+ *
 
73
+ * Emulate a virtual board which works by passing Linux all the information
 
74
+ * it needs about what devices are present via the device tree.
 
75
+ * There are some restrictions about what we can do here:
 
76
+ *  + we can only present devices whose Linux drivers will work based
 
77
+ *    purely on the device tree with no platform data at all
 
78
+ *  + we want to present a very stripped-down minimalist platform,
 
79
+ *    both because this reduces the security attack surface from the guest
 
80
+ *    and also because it reduces our exposure to being broken when
 
81
+ *    the kernel updates its device tree bindings and requires further
 
82
+ *    information in a device binding that we aren't providing.
 
83
+ * This is essentially the same approach kvmtool uses.
 
84
+ */
 
85
+
 
86
+#include "hw/sysbus.h"
 
87
+#include "hw/arm/arm.h"
 
88
+#include "hw/arm/primecell.h"
 
89
+#include "hw/devices.h"
 
90
+#include "net/net.h"
 
91
+#include "sysemu/device_tree.h"
 
92
+#include "sysemu/sysemu.h"
 
93
+#include "sysemu/kvm.h"
 
94
+#include "hw/boards.h"
 
95
+#include "exec/address-spaces.h"
 
96
+#include "qemu/bitops.h"
 
97
+#include "qemu/error-report.h"
 
98
+
 
99
+#define NUM_VIRTIO_TRANSPORTS 32
 
100
+
 
101
+/* Number of external interrupt lines to configure the GIC with */
 
102
+#define NUM_IRQS 128
 
103
+
 
104
+#define GIC_FDT_IRQ_TYPE_SPI 0
 
105
+#define GIC_FDT_IRQ_TYPE_PPI 1
 
106
+
 
107
+#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
 
108
+#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
 
109
+#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
 
110
+#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
 
111
+
 
112
+#define GIC_FDT_IRQ_PPI_CPU_START 8
 
113
+#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 
114
+
 
115
+enum {
 
116
+    VIRT_FLASH,
 
117
+    VIRT_MEM,
 
118
+    VIRT_CPUPERIPHS,
 
119
+    VIRT_GIC_DIST,
 
120
+    VIRT_GIC_CPU,
 
121
+    VIRT_UART,
 
122
+    VIRT_MMIO,
 
123
+};
 
124
+
 
125
+typedef struct MemMapEntry {
 
126
+    hwaddr base;
 
127
+    hwaddr size;
 
128
+} MemMapEntry;
 
129
+
 
130
+typedef struct VirtBoardInfo {
 
131
+    struct arm_boot_info bootinfo;
 
132
+    const char *cpu_model;
 
133
+    const char *qdevname;
 
134
+    const char *gic_compatible;
 
135
+    const MemMapEntry *memmap;
 
136
+    const int *irqmap;
 
137
+    int smp_cpus;
 
138
+    void *fdt;
 
139
+    int fdt_size;
 
140
+    uint32_t clock_phandle;
 
141
+} VirtBoardInfo;
 
142
+
 
143
+/* Addresses and sizes of our components.
 
144
+ * 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
 
145
+ * 128MB..256MB is used for miscellaneous device I/O.
 
146
+ * 256MB..1GB is reserved for possible future PCI support (ie where the
 
147
+ * PCI memory window will go if we add a PCI host controller).
 
148
+ * 1GB and up is RAM (which may happily spill over into the
 
149
+ * high memory region beyond 4GB).
 
150
+ * This represents a compromise between how much RAM can be given to
 
151
+ * a 32 bit VM and leaving space for expansion and in particular for PCI.
 
152
+ */
 
153
+static const MemMapEntry a15memmap[] = {
 
154
+    /* Space up to 0x8000000 is reserved for a boot ROM */
 
155
+    [VIRT_FLASH] = { 0, 0x8000000 },
 
156
+    [VIRT_CPUPERIPHS] = { 0x8000000, 0x8000 },
 
157
+    /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
 
158
+    [VIRT_GIC_DIST] = { 0x8001000, 0x1000 },
 
159
+    [VIRT_GIC_CPU] = { 0x8002000, 0x1000 },
 
160
+    [VIRT_UART] = { 0x9000000, 0x1000 },
 
161
+    [VIRT_MMIO] = { 0xa000000, 0x200 },
 
162
+    /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 
163
+    /* 0x10000000 .. 0x40000000 reserved for PCI */
 
164
+    [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
 
165
+};
 
166
+
 
167
+static const int a15irqmap[] = {
 
168
+    [VIRT_UART] = 1,
 
169
+    [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
 
170
+};
 
171
+
 
172
+static VirtBoardInfo machines[] = {
 
173
+    {
 
174
+        .cpu_model = "cortex-a15",
 
175
+        .qdevname = "a15mpcore_priv",
 
176
+        .gic_compatible = "arm,cortex-a15-gic",
 
177
+        .memmap = a15memmap,
 
178
+        .irqmap = a15irqmap,
 
179
+    },
 
180
+};
 
181
+
 
182
+static VirtBoardInfo *find_machine_info(const char *cpu)
 
183
+{
 
184
+    int i;
 
185
+
 
186
+    for (i = 0; i < ARRAY_SIZE(machines); i++) {
 
187
+        if (strcmp(cpu, machines[i].cpu_model) == 0) {
 
188
+            return &machines[i];
 
189
+        }
 
190
+    }
 
191
+    return NULL;
 
192
+}
 
193
+
 
194
+static void create_fdt(VirtBoardInfo *vbi)
 
195
+{
 
196
+    void *fdt = create_device_tree(&vbi->fdt_size);
 
197
+
 
198
+    if (!fdt) {
 
199
+        error_report("create_device_tree() failed");
 
200
+        exit(1);
 
201
+    }
 
202
+
 
203
+    vbi->fdt = fdt;
 
204
+
 
205
+    /* Header */
 
206
+    qemu_devtree_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
 
207
+    qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 0x2);
 
208
+    qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 0x2);
 
209
+
 
210
+    /*
 
211
+     * /chosen and /memory nodes must exist for load_dtb
 
212
+     * to fill in necessary properties later
 
213
+     */
 
214
+    qemu_devtree_add_subnode(fdt, "/chosen");
 
215
+    qemu_devtree_add_subnode(fdt, "/memory");
 
216
+    qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
 
217
+
 
218
+    /* Clock node, for the benefit of the UART. The kernel device tree
 
219
+     * binding documentation claims the PL011 node clock properties are
 
220
+     * optional but in practice if you omit them the kernel refuses to
 
221
+     * probe for the device.
 
222
+     */
 
223
+    vbi->clock_phandle = qemu_devtree_alloc_phandle(fdt);
 
224
+    qemu_devtree_add_subnode(fdt, "/apb-pclk");
 
225
+    qemu_devtree_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
 
226
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
 
227
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
 
228
+    qemu_devtree_setprop_string(fdt, "/apb-pclk", "clock-output-names",
 
229
+                                "clk24mhz");
 
230
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
 
231
+
 
232
+    /* No PSCI for TCG yet */
 
233
+    if (kvm_enabled()) {
 
234
+        qemu_devtree_add_subnode(fdt, "/psci");
 
235
+        qemu_devtree_setprop_string(fdt, "/psci", "compatible", "arm,psci");
 
236
+        qemu_devtree_setprop_string(fdt, "/psci", "method", "hvc");
 
237
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_suspend",
 
238
+                                  PSCI_FN_CPU_SUSPEND);
 
239
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_off", PSCI_FN_CPU_OFF);
 
240
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_on", PSCI_FN_CPU_ON);
 
241
+        qemu_devtree_setprop_cell(fdt, "/psci", "migrate", PSCI_FN_MIGRATE);
 
242
+    }
 
243
+}
 
244
+
 
245
+static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
 
246
+{
 
247
+    /* Note that on A15 h/w these interrupts are level-triggered,
 
248
+     * but for the GIC implementation provided by both QEMU and KVM
 
249
+     * they are edge-triggered.
 
250
+     */
 
251
+    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
 
252
+
 
253
+    irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
 
254
+                         GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
 
255
+
 
256
+    qemu_devtree_add_subnode(vbi->fdt, "/timer");
 
257
+    qemu_devtree_setprop_string(vbi->fdt, "/timer",
 
258
+                                "compatible", "arm,armv7-timer");
 
259
+    qemu_devtree_setprop_cells(vbi->fdt, "/timer", "interrupts",
 
260
+                               GIC_FDT_IRQ_TYPE_PPI, 13, irqflags,
 
261
+                               GIC_FDT_IRQ_TYPE_PPI, 14, irqflags,
 
262
+                               GIC_FDT_IRQ_TYPE_PPI, 11, irqflags,
 
263
+                               GIC_FDT_IRQ_TYPE_PPI, 10, irqflags);
 
264
+}
 
265
+
 
266
+static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
 
267
+{
 
268
+    int cpu;
 
269
+
 
270
+    qemu_devtree_add_subnode(vbi->fdt, "/cpus");
 
271
+    qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
 
272
+    qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
 
273
+
 
274
+    for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) {
 
275
+        char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
 
276
+        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
 
277
+
 
278
+        qemu_devtree_add_subnode(vbi->fdt, nodename);
 
279
+        qemu_devtree_setprop_string(vbi->fdt, nodename, "device_type", "cpu");
 
280
+        qemu_devtree_setprop_string(vbi->fdt, nodename, "compatible",
 
281
+                                    armcpu->dtb_compatible);
 
282
+
 
283
+        if (vbi->smp_cpus > 1) {
 
284
+            qemu_devtree_setprop_string(vbi->fdt, nodename,
 
285
+                                        "enable-method", "psci");
 
286
+        }
 
287
+
 
288
+        qemu_devtree_setprop_cell(vbi->fdt, nodename, "reg", cpu);
 
289
+        g_free(nodename);
 
290
+    }
 
291
+}
 
292
+
 
293
+static void fdt_add_gic_node(const VirtBoardInfo *vbi)
 
294
+{
 
295
+    uint32_t gic_phandle;
 
296
+
 
297
+    gic_phandle = qemu_devtree_alloc_phandle(vbi->fdt);
 
298
+    qemu_devtree_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
 
299
+
 
300
+    qemu_devtree_add_subnode(vbi->fdt, "/intc");
 
301
+    qemu_devtree_setprop_string(vbi->fdt, "/intc", "compatible",
 
302
+                                vbi->gic_compatible);
 
303
+    qemu_devtree_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
 
304
+    qemu_devtree_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
 
305
+    qemu_devtree_setprop_sized_cells(vbi->fdt, "/intc", "reg",
 
306
+                                     2, vbi->memmap[VIRT_GIC_DIST].base,
 
307
+                                     2, vbi->memmap[VIRT_GIC_DIST].size,
 
308
+                                     2, vbi->memmap[VIRT_GIC_CPU].base,
 
309
+                                     2, vbi->memmap[VIRT_GIC_CPU].size);
 
310
+    qemu_devtree_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
 
311
+}
 
312
+
 
313
+static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
 
314
+{
 
315
+    char *nodename;
 
316
+    hwaddr base = vbi->memmap[VIRT_UART].base;
 
317
+    hwaddr size = vbi->memmap[VIRT_UART].size;
 
318
+    int irq = vbi->irqmap[VIRT_UART];
 
319
+    const char compat[] = "arm,pl011\0arm,primecell";
 
320
+    const char clocknames[] = "uartclk\0apb_pclk";
 
321
+
 
322
+    sysbus_create_simple("pl011", base, pic[irq]);
 
323
+
 
324
+    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
 
325
+    qemu_devtree_add_subnode(vbi->fdt, nodename);
 
326
+    /* Note that we can't use setprop_string because of the embedded NUL */
 
327
+    qemu_devtree_setprop(vbi->fdt, nodename, "compatible",
 
328
+                         compat, sizeof(compat));
 
329
+    qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
 
330
+                                     2, base, 2, size);
 
331
+    qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
 
332
+                               GIC_FDT_IRQ_TYPE_SPI, irq,
 
333
+                               GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
 
334
+    qemu_devtree_setprop_cells(vbi->fdt, nodename, "clocks",
 
335
+                               vbi->clock_phandle, vbi->clock_phandle);
 
336
+    qemu_devtree_setprop(vbi->fdt, nodename, "clock-names",
 
337
+                         clocknames, sizeof(clocknames));
 
338
+    g_free(nodename);
 
339
+}
 
340
+
 
341
+static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
 
342
+{
 
343
+    int i;
 
344
+    hwaddr size = vbi->memmap[VIRT_MMIO].size;
 
345
+
 
346
+    /* Note that we have to create the transports in forwards order
 
347
+     * so that command line devices are inserted lowest address first,
 
348
+     * and then add dtb nodes in reverse order so that they appear in
 
349
+     * the finished device tree lowest address first.
 
350
+     */
 
351
+    for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
 
352
+        int irq = vbi->irqmap[VIRT_MMIO] + i;
 
353
+        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
 
354
+
 
355
+        sysbus_create_simple("virtio-mmio", base, pic[irq]);
 
356
+    }
 
357
+
 
358
+    for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
 
359
+        char *nodename;
 
360
+        int irq = vbi->irqmap[VIRT_MMIO] + i;
 
361
+        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
 
362
+
 
363
+        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
 
364
+        qemu_devtree_add_subnode(vbi->fdt, nodename);
 
365
+        qemu_devtree_setprop_string(vbi->fdt, nodename,
 
366
+                                    "compatible", "virtio,mmio");
 
367
+        qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
 
368
+                                         2, base, 2, size);
 
369
+        qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
 
370
+                                   GIC_FDT_IRQ_TYPE_SPI, irq,
 
371
+                                   GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
 
372
+        g_free(nodename);
 
373
+    }
 
374
+}
 
375
+
 
376
+static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 
377
+{
 
378
+    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
 
379
+
 
380
+    *fdt_size = board->fdt_size;
 
381
+    return board->fdt;
 
382
+}
 
383
+
 
384
+static void machvirt_init(QEMUMachineInitArgs *args)
 
385
+{
 
386
+    qemu_irq pic[NUM_IRQS];
 
387
+    MemoryRegion *sysmem = get_system_memory();
 
388
+    int n;
 
389
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
 
390
+    DeviceState *dev;
 
391
+    SysBusDevice *busdev;
 
392
+    const char *cpu_model = args->cpu_model;
 
393
+    VirtBoardInfo *vbi;
 
394
+
 
395
+    if (!cpu_model) {
 
396
+        cpu_model = "cortex-a15";
 
397
+    }
 
398
+
 
399
+    vbi = find_machine_info(cpu_model);
 
400
+
 
401
+    if (!vbi) {
 
402
+        error_report("mach-virt: CPU %s not supported", cpu_model);
 
403
+        exit(1);
 
404
+    }
 
405
+
 
406
+    vbi->smp_cpus = smp_cpus;
 
407
+
 
408
+    /*
 
409
+     * Only supported method of starting secondary CPUs is PSCI and
 
410
+     * PSCI is not yet supported with TCG, so limit smp_cpus to 1
 
411
+     * if we're not using KVM.
 
412
+     */
 
413
+    if (!kvm_enabled() && smp_cpus > 1) {
 
414
+        error_report("mach-virt: must enable KVM to use multiple CPUs");
 
415
+        exit(1);
 
416
+    }
 
417
+
 
418
+    if (args->ram_size > vbi->memmap[VIRT_MEM].size) {
 
419
+        error_report("mach-virt: cannot model more than 30GB RAM");
 
420
+        exit(1);
 
421
+    }
 
422
+
 
423
+    create_fdt(vbi);
 
424
+    fdt_add_timer_nodes(vbi);
 
425
+
 
426
+    for (n = 0; n < smp_cpus; n++) {
 
427
+        ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
 
428
+        Object *cpuobj;
 
429
+
 
430
+        if (!oc) {
 
431
+            fprintf(stderr, "Unable to find CPU definition\n");
 
432
+            exit(1);
 
433
+        }
 
434
+        cpuobj = object_new(object_class_get_name(oc));
 
435
+
 
436
+        /* Secondary CPUs start in PSCI powered-down state */
 
437
+        if (n > 0) {
 
438
+            object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
 
439
+        }
 
440
+        object_property_set_bool(cpuobj, true, "realized", NULL);
 
441
+    }
 
442
+    fdt_add_cpu_nodes(vbi);
 
443
+
 
444
+    memory_region_init_ram(ram, NULL, "mach-virt.ram", args->ram_size);
 
445
+    vmstate_register_ram_global(ram);
 
446
+    memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
 
447
+
 
448
+    dev = qdev_create(NULL, vbi->qdevname);
 
449
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
 
450
+    /* Note that the num-irq property counts both internal and external
 
451
+     * interrupts; there are always 32 of the former (mandated by GIC spec).
 
452
+     */
 
453
+    qdev_prop_set_uint32(dev, "num-irq", NUM_IRQS + 32);
 
454
+    qdev_init_nofail(dev);
 
455
+    busdev = SYS_BUS_DEVICE(dev);
 
456
+    sysbus_mmio_map(busdev, 0, vbi->memmap[VIRT_CPUPERIPHS].base);
 
457
+    fdt_add_gic_node(vbi);
 
458
+    for (n = 0; n < smp_cpus; n++) {
 
459
+        DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
 
460
+
 
461
+        sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
 
462
+    }
 
463
+
 
464
+    for (n = 0; n < NUM_IRQS; n++) {
 
465
+        pic[n] = qdev_get_gpio_in(dev, n);
 
466
+    }
 
467
+
 
468
+    create_uart(vbi, pic);
 
469
+
 
470
+    /* Create mmio transports, so the user can create virtio backends
 
471
+     * (which will be automatically plugged in to the transports). If
 
472
+     * no backend is created the transport will just sit harmlessly idle.
 
473
+     */
 
474
+    create_virtio_devices(vbi, pic);
 
475
+
 
476
+    vbi->bootinfo.ram_size = args->ram_size;
 
477
+    vbi->bootinfo.kernel_filename = args->kernel_filename;
 
478
+    vbi->bootinfo.kernel_cmdline = args->kernel_cmdline;
 
479
+    vbi->bootinfo.initrd_filename = args->initrd_filename;
 
480
+    vbi->bootinfo.nb_cpus = smp_cpus;
 
481
+    vbi->bootinfo.board_id = -1;
 
482
+    vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
 
483
+    vbi->bootinfo.get_dtb = machvirt_dtb;
 
484
+    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
 
485
+}
 
486
+
 
487
+static QEMUMachine machvirt_a15_machine = {
 
488
+    .name = "virt",
 
489
+    .desc = "ARM Virtual Machine",
 
490
+    .init = machvirt_init,
 
491
+    .max_cpus = 4,
 
492
+};
 
493
+
 
494
+static void machvirt_machine_init(void)
 
495
+{
 
496
+    qemu_register_machine(&machvirt_a15_machine);
 
497
+}
 
498
+
 
499
+machine_init(machvirt_machine_init);