summaryrefslogtreecommitdiffstats
path: root/hw/arm
diff options
context:
space:
mode:
authorPeter Maydell2019-01-07 17:56:32 +0100
committerPeter Maydell2019-01-07 17:56:33 +0100
commitc102d9471f8f02d9fbea72ec4505d7089173f470 (patch)
tree564bc224680b5f34f4e48fe28c4c11ec55862b69 /hw/arm
parentMerge remote-tracking branch 'remotes/elmarco/tags/machine-props-pull-request... (diff)
parentSupport u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. (diff)
downloadqemu-c102d9471f8f02d9fbea72ec4505d7089173f470.tar.gz
qemu-c102d9471f8f02d9fbea72ec4505d7089173f470.tar.xz
qemu-c102d9471f8f02d9fbea72ec4505d7089173f470.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190107' into staging
target-arm queue: * Support u-boot 'noload' images for Arm (as used by NetBSD/evbarm GENERIC kernel) * hw/misc/tz-mpc: Fix value of BLK_MAX register * target/arm: Emit barriers for A32/T32 load-acquire/store-release insns * nRF51 SoC: add timer, GPIO, RNG peripherals * hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller * cpus.c: Fix race condition in cpu_stop_current() * hw/arm: versal: Plug memory leaks * Allow M profile boards to run even if -kernel not specified * gdbstub: Add multiprocess extension support for use when the board has multiple CPUs of different types (like the Xilinx Zynq boards) * target/arm: Don't decode S bit in SVE brk[ab] merging insns * target/arm: Convert ARM_TBFLAG_* to FIELDs # gpg: Signature made Mon 07 Jan 2019 16:29:52 GMT # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20190107: (37 commits) Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. hw/misc/tz-mpc: Fix value of BLK_MAX register target/arm: Emit barriers for A32/T32 load-acquire/store-release insns arm: Add Clock peripheral stub to NRF51 SOC tests/microbit-test: Add Tests for nRF51 Timer arm: Instantiate NRF51 Timers hw/timer/nrf51_timer: Add nRF51 Timer peripheral tests/microbit-test: Add Tests for nRF51 GPIO arm: Instantiate NRF51 general purpose I/O hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral arm: Instantiate NRF51 random number generator hw/misc/nrf51_rng: Add NRF51 random number generator peripheral arm: Add header to host common definition for nRF51 SOC peripherals qtest: Add set_irq_in command to set IRQ/GPIO level hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller cpus.c: Fix race condition in cpu_stop_current() MAINTAINERS: Add ARM-related files for hw/[misc|input|timer]/ hw/arm: versal: Plug memory leaks Revert "armv7m: Guard against no -kernel argument" arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/allwinner-a10.c6
-rw-r--r--hw/arm/armv7m.c5
-rw-r--r--hw/arm/boot.c8
-rw-r--r--hw/arm/nrf51_soc.c117
-rw-r--r--hw/arm/xlnx-versal-virt.c2
-rw-r--r--hw/arm/xlnx-zynqmp.c23
6 files changed, 128 insertions, 33 deletions
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 9fe875cdb5..df0d079ad0 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -22,6 +22,7 @@
#include "hw/sysbus.h"
#include "hw/devices.h"
#include "hw/arm/allwinner-a10.h"
+#include "hw/misc/unimp.h"
static void aw_a10_init(Object *obj)
{
@@ -85,6 +86,11 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
+ memory_region_init_ram(&s->sram_a, OBJECT(dev), "sram A", 48 * KiB,
+ &error_fatal);
+ memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
+ create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
+
/* FIXME use qdev NIC properties instead of nd_table[] */
if (nd_table[0].used) {
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 4bf9131b81..f444652830 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -285,11 +285,6 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
big_endian = 0;
#endif
- if (!kernel_filename && !qtest_enabled()) {
- error_report("Guest image must be specified (using -kernel)");
- exit(1);
- }
-
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
asidx = ARMASIdx_S;
} else {
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 94fce12802..c7a67af7a9 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -30,8 +30,9 @@
* Documentation/arm/Booting and Documentation/arm64/booting.txt
* They have different preferred image load offsets from system RAM base.
*/
-#define KERNEL_ARGS_ADDR 0x100
-#define KERNEL_LOAD_ADDR 0x00010000
+#define KERNEL_ARGS_ADDR 0x100
+#define KERNEL_NOLOAD_ADDR 0x02000000
+#define KERNEL_LOAD_ADDR 0x00010000
#define KERNEL64_LOAD_ADDR 0x00080000
#define ARM64_TEXT_OFFSET_OFFSET 8
@@ -1082,7 +1083,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
}
entry = elf_entry;
if (kernel_size < 0) {
- kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
+ uint64_t loadaddr = info->loader_start + KERNEL_NOLOAD_ADDR;
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, &loadaddr,
&is_linux, NULL, NULL, as);
}
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index b89c1bdea0..1630c27594 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -21,35 +21,46 @@
#include "qemu/log.h"
#include "cpu.h"
+#include "hw/arm/nrf51.h"
#include "hw/arm/nrf51_soc.h"
-#define IOMEM_BASE 0x40000000
-#define IOMEM_SIZE 0x20000000
-
-#define FICR_BASE 0x10000000
-#define FICR_SIZE 0x000000fc
-
-#define FLASH_BASE 0x00000000
-#define SRAM_BASE 0x20000000
-
-#define PRIVATE_BASE 0xF0000000
-#define PRIVATE_SIZE 0x10000000
-
/*
* The size and base is for the NRF51822 part. If other parts
* are supported in the future, add a sub-class of NRF51SoC for
* the specific variants
*/
-#define NRF51822_FLASH_SIZE (256 * 1024)
-#define NRF51822_SRAM_SIZE (16 * 1024)
+#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE)
+#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE)
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
+static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
+ __func__, addr, size);
+ return 1;
+}
+
+static void clock_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
+ __func__, addr, data, size);
+}
+
+static const MemoryRegionOps clock_ops = {
+ .read = clock_read,
+ .write = clock_write
+};
+
+
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
{
NRF51State *s = NRF51_SOC(dev_soc);
MemoryRegion *mr;
Error *err = NULL;
+ uint8_t i = 0;
+ hwaddr base_addr = 0;
if (!s->board_memory) {
error_setg(errp, "memory property was not set");
@@ -76,14 +87,14 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
error_propagate(errp, err);
return;
}
- memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
+ memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
if (err) {
error_propagate(errp, err);
return;
}
- memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
+ memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram);
/* UART */
object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
@@ -92,19 +103,71 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
return;
}
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
- memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
+ memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
qdev_get_gpio_in(DEVICE(&s->cpu),
- BASE_TO_IRQ(UART_BASE)));
+ BASE_TO_IRQ(NRF51_UART_BASE)));
+
+ /* RNG */
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0);
+ memory_region_add_subregion_overlap(&s->container, NRF51_RNG_BASE, mr, 0);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0,
+ qdev_get_gpio_in(DEVICE(&s->cpu),
+ BASE_TO_IRQ(NRF51_RNG_BASE)));
+
+ /* GPIO */
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0);
+ memory_region_add_subregion_overlap(&s->container, NRF51_GPIO_BASE, mr, 0);
+
+ /* Pass all GPIOs to the SOC layer so they are available to the board */
+ qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
+
+ /* TIMER */
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
+ object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE;
- create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
- create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->cpu),
+ BASE_TO_IRQ(base_addr)));
+ }
+
+ /* STUB Peripherals */
+ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL,
+ "nrf51_soc.clock", 0x1000);
+ memory_region_add_subregion_overlap(&s->container,
+ NRF51_IOMEM_BASE, &s->clock, -1);
+
+ create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
+ NRF51_IOMEM_SIZE);
+ create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
+ NRF51_FICR_SIZE);
create_unimplemented_device("nrf51_soc.private",
- PRIVATE_BASE, PRIVATE_SIZE);
+ NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
}
static void nrf51_soc_init(Object *obj)
{
+ uint8_t i = 0;
+
NRF51State *s = NRF51_SOC(obj);
memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX);
@@ -119,6 +182,18 @@ static void nrf51_soc_init(Object *obj)
TYPE_NRF51_UART);
object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
&error_abort);
+
+ sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
+ TYPE_NRF51_RNG);
+
+ sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
+ TYPE_NRF51_GPIO);
+
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
+ sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
+ sizeof(s->timer[i]), TYPE_NRF51_TIMER);
+
+ }
}
static Property nrf51_soc_properties[] = {
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index c6feeac532..f95fde2309 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -130,6 +130,7 @@ static void fdt_add_gic_nodes(VersalVirt *s)
2, MM_GIC_APU_REDIST_0_SIZE);
qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
+ g_free(nodename);
}
static void fdt_add_timer_nodes(VersalVirt *s)
@@ -364,6 +365,7 @@ static void create_virtio_regions(VersalVirt *s)
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
memory_region_add_subregion(&s->soc.mr_ps, base, mr);
+ g_free(name);
}
for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index c195040350..c67ac2e64a 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -178,12 +178,19 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
int i;
int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS);
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster,
+ sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER,
+ &error_abort, NULL);
+ qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1);
+
+ qdev_init_nofail(DEVICE(&s->rpu_cluster));
+
for (i = 0; i < num_rpus; i++) {
char *name;
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
"cortex-r5f-" TYPE_ARM_CPU);
- object_property_add_child(OBJECT(s), "rpu-cpu[*]",
+ object_property_add_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]",
OBJECT(&s->rpu_cpu[i]), &error_abort);
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
@@ -213,10 +220,16 @@ static void xlnx_zynqmp_init(Object *obj)
int i;
int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
+ object_initialize_child(obj, "apu-cluster", &s->apu_cluster,
+ sizeof(s->apu_cluster), TYPE_CPU_CLUSTER,
+ &error_abort, NULL);
+ qdev_prop_set_uint32(DEVICE(&s->apu_cluster), "cluster-id", 0);
+
for (i = 0; i < num_apus; i++) {
- object_initialize_child(obj, "apu-cpu[*]", &s->apu_cpu[i],
- sizeof(s->apu_cpu[i]),
- "cortex-a53-" TYPE_ARM_CPU, &error_abort, NULL);
+ object_initialize_child(OBJECT(&s->apu_cluster), "apu-cpu[*]",
+ &s->apu_cpu[i], sizeof(s->apu_cpu[i]),
+ "cortex-a53-" TYPE_ARM_CPU, &error_abort,
+ NULL);
}
sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
@@ -333,6 +346,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qdev_prop_set_bit(DEVICE(&s->gic),
"has-virtualization-extensions", s->virt);
+ qdev_init_nofail(DEVICE(&s->apu_cluster));
+
/* Realize APUs before realizing the GIC. KVM requires this. */
for (i = 0; i < num_apus; i++) {
char *name;