summaryrefslogtreecommitdiffstats
path: root/hw/arm/mps2-tz.c
diff options
context:
space:
mode:
authorPeter Maydell2019-02-01 17:39:17 +0100
committerPeter Maydell2019-02-01 17:39:17 +0100
commite83d74286cad2b9b967e1ba0ce5c8d16cba9679f (patch)
treebd57034a1550568ec8f9d6aa4457fd38531e9c17 /hw/arm/mps2-tz.c
parentMerge remote-tracking branch 'remotes/kraxel/tags/ui-20190201-pull-request' i... (diff)
parenttests/microbit-test: Add tests for nRF51 NVMC (diff)
downloadqemu-e83d74286cad2b9b967e1ba0ce5c8d16cba9679f.tar.gz
qemu-e83d74286cad2b9b967e1ba0ce5c8d16cba9679f.tar.xz
qemu-e83d74286cad2b9b967e1ba0ce5c8d16cba9679f.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190201' into staging
target-arm queue: * New machine mps2-an521 -- this is a model of the AN521 FPGA image for the MPS2 devboard * Fix various places where we failed to UNDEF invalid A64 instructions * Don't UNDEF a valid FCMLA on 32-bit inputs * Fix some bugs in the newly-added PAuth implementation * microbit: Implement NVMC non-volatile memory controller # gpg: Signature made Fri 01 Feb 2019 16:06:03 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20190201: (47 commits) tests/microbit-test: Add tests for nRF51 NVMC arm: Instantiate NRF51 special NVM's and NVMC hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories target/arm: fix decoding of B{,L}RA{A,B} target/arm: fix AArch64 virtual address space size linux-user: Initialize aarch64 pac keys aarch64-linux-user: Enable HWCAP bits for PAuth aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1 target/arm: Always enable pac keys for user-only arm: Clarify the logic of set_pc() target/arm: Enable API, APK bits in SCR, HCR target/arm: Add a timer to predict PMU counter overflow target/arm: Send interrupts on PMU counter overflow target/arm/translate-a64: Fix mishandling of size in FCMLA decode target/arm/translate-a64: Fix FCMLA decoding error exec.c: Don't reallocate IOMMUNotifiers that are in use target/arm/translate-a64: Don't underdecode SDOT and UDOT target/arm/translate-a64: Don't underdecode FP insns target/arm/translate-a64: Don't underdecode add/sub extended register target/arm/translate-a64: Don't underdecode SIMD ld/st single ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/mps2-tz.c')
-rw-r--r--hw/arm/mps2-tz.c121
1 files changed, 97 insertions, 24 deletions
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 82b1d020a5..f5f0b0e0fa 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -15,6 +15,7 @@
* as seen by the guest depend significantly on the FPGA image.
* This source file covers the following FPGA images, for TrustZone cores:
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
+ * "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
*
* Links to the TRM for the board itself and to the various Application
* Notes which document the FPGA images can be found here:
@@ -24,10 +25,16 @@
* http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
* Application Note AN505:
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
+ * Application Note AN521:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
*
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
* (ARM ECM0601256) for the details of some of the device layout:
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
+ * most of the device layout:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
*/
#include "qemu/osdep.h"
@@ -46,27 +53,31 @@
#include "hw/misc/mps2-fpgaio.h"
#include "hw/misc/tz-mpc.h"
#include "hw/misc/tz-msc.h"
-#include "hw/arm/iotkit.h"
+#include "hw/arm/armsse.h"
#include "hw/dma/pl080.h"
#include "hw/ssi/pl022.h"
#include "hw/devices.h"
#include "net/net.h"
#include "hw/core/split-irq.h"
+#define MPS2TZ_NUMIRQ 92
+
typedef enum MPS2TZFPGAType {
FPGA_AN505,
+ FPGA_AN521,
} MPS2TZFPGAType;
typedef struct {
MachineClass parent;
MPS2TZFPGAType fpga_type;
uint32_t scc_id;
+ const char *armsse_type;
} MPS2TZMachineClass;
typedef struct {
MachineState parent;
- IoTKit iotkit;
+ ARMSSE iotkit;
MemoryRegion psram;
MemoryRegion ssram[3];
MemoryRegion ssram1_m;
@@ -85,10 +96,12 @@ typedef struct {
SplitIRQ sec_resp_splitter;
qemu_or_irq uart_irq_orgate;
DeviceState *lan9118;
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
} MPS2TZMachineState;
#define TYPE_MPS2TZ_MACHINE "mps2tz"
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
+#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
#define MPS2TZ_MACHINE(obj) \
OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
@@ -111,6 +124,23 @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
memory_region_add_subregion(get_system_memory(), base, mr);
}
+static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
+{
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
+
+ assert(irqno < MPS2TZ_NUMIRQ);
+
+ switch (mmc->fpga_type) {
+ case FPGA_AN505:
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
+ case FPGA_AN521:
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
+ default:
+ g_assert_not_reached();
+ }
+}
+
/* Most of the devices in the AN505 FPGA image sit behind
* Peripheral Protection Controllers. These data structures
* define the layout of which devices sit behind which PPCs.
@@ -161,7 +191,6 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
int txirqno = i * 2 + 1;
int combirqno = i + 10;
SysBusDevice *s;
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
@@ -170,14 +199,11 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
s = SYS_BUS_DEVICE(uart);
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", txirqno));
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", rxirqno));
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
- sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", combirqno));
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
}
@@ -213,7 +239,6 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
const char *name, hwaddr size)
{
SysBusDevice *s;
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
NICInfo *nd = &nd_table[0];
/* In hardware this is a LAN9220; the LAN9118 is software compatible
@@ -225,7 +250,7 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
qdev_init_nofail(mms->lan9118);
s = SYS_BUS_DEVICE(mms->lan9118);
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
return sysbus_mmio_get_region(s, 0);
}
@@ -315,12 +340,9 @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
s = SYS_BUS_DEVICE(dma);
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", 58 + i * 3));
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", 56 + i * 3));
- sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
- "EXP_IRQ", 57 + i * 3));
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
g_free(mscname);
return sysbus_mmio_get_region(s, 0);
@@ -339,21 +361,20 @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
*/
PL022State *spi = opaque;
int i = spi - &mms->spi[0];
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
SysBusDevice *s;
sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
TYPE_PL022);
object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
s = SYS_BUS_DEVICE(spi);
- sysbus_connect_irq(s, 0,
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
return sysbus_mmio_get_region(s, 0);
}
static void mps2tz_common_init(MachineState *machine)
{
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
MachineClass *mc = MACHINE_GET_CLASS(machine);
MemoryRegion *system_memory = get_system_memory();
DeviceState *iotkitdev;
@@ -367,15 +388,42 @@ static void mps2tz_common_init(MachineState *machine)
}
sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
- sizeof(mms->iotkit), TYPE_IOTKIT);
+ sizeof(mms->iotkit), mmc->armsse_type);
iotkitdev = DEVICE(&mms->iotkit);
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
"memory", &error_abort);
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
&error_fatal);
+ /*
+ * The AN521 needs us to create splitters to feed the IRQ inputs
+ * for each CPU in the SSE-200 from each device in the board.
+ */
+ if (mmc->fpga_type == FPGA_AN521) {
+ for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
+ char *name = g_strdup_printf("mps2-irq-splitter%d", i);
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
+
+ object_initialize_child(OBJECT(machine), name,
+ splitter, sizeof(*splitter),
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
+ g_free(name);
+
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
+ &error_fatal);
+ object_property_set_bool(OBJECT(splitter), true, "realized",
+ &error_fatal);
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
+ "EXP_IRQ", i));
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
+ "EXP_CPU1_IRQ", i));
+ }
+ }
+
/* The sec_resp_cfg output from the IoTKit must be split into multiple
* lines, one for each of the PPCs we create here, plus one per MSC.
*/
@@ -426,7 +474,7 @@ static void mps2tz_common_init(MachineState *machine)
object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
"realized", &error_fatal);
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
+ get_sse_irq_in(mms, 15));
/* Most of the devices in the FPGA are behind Peripheral Protection
* Controllers. The required order for initializing things is:
@@ -593,7 +641,6 @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
mc->init = mps2tz_common_init;
- mc->max_cpus = 1;
iic->check = mps2_tz_idau_check;
}
@@ -603,9 +650,28 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
+ mc->default_cpus = 1;
+ mc->min_cpus = mc->default_cpus;
+ mc->max_cpus = mc->default_cpus;
mmc->fpga_type = FPGA_AN505;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
mmc->scc_id = 0x41045050;
+ mmc->armsse_type = TYPE_IOTKIT;
+}
+
+static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
+
+ mc->desc = "ARM MPS2 with AN521 FPGA image for dual Cortex-M33";
+ mc->default_cpus = 2;
+ mc->min_cpus = mc->default_cpus;
+ mc->max_cpus = mc->default_cpus;
+ mmc->fpga_type = FPGA_AN521;
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
+ mmc->scc_id = 0x41045210;
+ mmc->armsse_type = TYPE_SSE200;
}
static const TypeInfo mps2tz_info = {
@@ -627,10 +693,17 @@ static const TypeInfo mps2tz_an505_info = {
.class_init = mps2tz_an505_class_init,
};
+static const TypeInfo mps2tz_an521_info = {
+ .name = TYPE_MPS2TZ_AN521_MACHINE,
+ .parent = TYPE_MPS2TZ_MACHINE,
+ .class_init = mps2tz_an521_class_init,
+};
+
static void mps2tz_machine_init(void)
{
type_register_static(&mps2tz_info);
type_register_static(&mps2tz_an505_info);
+ type_register_static(&mps2tz_an521_info);
}
type_init(mps2tz_machine_init);