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>
This commit is contained in:
Peter Maydell
2019-02-01 16:39:17 +00:00
36 changed files with 2552 additions and 941 deletions
+4 -2
View File
@@ -624,14 +624,16 @@ F: hw/arm/mps2.c
F: hw/arm/mps2-tz.c
F: hw/misc/mps2-*.c
F: include/hw/misc/mps2-*.h
F: hw/arm/iotkit.c
F: include/hw/arm/iotkit.h
F: hw/arm/armsse.c
F: include/hw/arm/armsse.h
F: hw/misc/iotkit-secctl.c
F: include/hw/misc/iotkit-secctl.h
F: hw/misc/iotkit-sysctl.c
F: include/hw/misc/iotkit-sysctl.h
F: hw/misc/iotkit-sysinfo.c
F: include/hw/misc/iotkit-sysinfo.h
F: hw/misc/armsse-cpuid.c
F: include/hw/misc/armsse-cpuid.h
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
+2 -1
View File
@@ -114,10 +114,11 @@ CONFIG_MPS2_SCC=y
CONFIG_TZ_MPC=y
CONFIG_TZ_MSC=y
CONFIG_TZ_PPC=y
CONFIG_IOTKIT=y
CONFIG_ARMSSE=y
CONFIG_IOTKIT_SECCTL=y
CONFIG_IOTKIT_SYSCTL=y
CONFIG_IOTKIT_SYSINFO=y
CONFIG_ARMSSE_CPUID=y
CONFIG_VERSATILE=y
CONFIG_VERSATILE_PCI=y
+6 -4
View File
@@ -665,7 +665,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
int i;
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
break;
}
@@ -673,7 +673,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
if (i == cpu->iommu_notifiers->len) {
/* Not found, add a new entry at the end of the array */
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
notifier = g_new0(TCGIOMMUNotifier, 1);
g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
notifier->mr = mr;
notifier->iommu_idx = iommu_idx;
@@ -705,8 +706,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
TCGIOMMUNotifier *notifier;
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
g_free(notifier);
}
g_array_free(cpu->iommu_notifiers, true);
}
@@ -976,7 +978,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
}
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
#endif
}
+1 -1
View File
@@ -34,7 +34,7 @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
obj-$(CONFIG_MPS2) += mps2.o
obj-$(CONFIG_MPS2) += mps2-tz.o
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
obj-$(CONFIG_IOTKIT) += iotkit.o
obj-$(CONFIG_ARMSSE) += armsse.o
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
+1241
View File
File diff suppressed because it is too large Load Diff
+20 -3
View File
@@ -158,7 +158,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
s->cpu = ARM_CPU(object_new(s->cpu_type));
s->cpu = ARM_CPU(object_new_with_props(s->cpu_type, OBJECT(s), "cpu",
&err, NULL));
if (err != NULL) {
error_propagate(errp, err);
return;
}
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
&error_abort);
@@ -177,11 +182,21 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
return;
}
}
if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) {
object_property_set_bool(OBJECT(s->cpu), s->start_powered_off,
"start-powered-off", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
}
/* Tell the CPU where the NVIC is; it will fail realize if it doesn't
* have one.
/*
* Tell the CPU where the NVIC is; it will fail realize if it doesn't
* have one. Similarly, tell the NVIC where its CPU is.
*/
s->cpu->env.nvic = &s->nvic;
s->nvic.cpu = s->cpu;
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
if (err != NULL) {
@@ -243,6 +258,8 @@ static Property armv7m_properties[] = {
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
false),
DEFINE_PROP_END_OF_LIST(),
};
-4
View File
@@ -697,10 +697,6 @@ static void do_cpu_reset(void *opaque)
g_assert_not_reached();
}
if (!env->aarch64) {
env->thumb = info->entry & 1;
entry &= 0xfffffffe;
}
cpu_set_pc(cs, entry);
} else {
/* If we are booting Linux then we need to check whether we are
-759
View File
File diff suppressed because it is too large Load Diff
+97 -24
View File
@@ -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);
+31 -13
View File
@@ -29,8 +29,10 @@
* are supported in the future, add a sub-class of NRF51SoC for
* the specific variants
*/
#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE)
#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE)
#define NRF51822_FLASH_PAGES 256
#define NRF51822_SRAM_PAGES 16
#define NRF51822_FLASH_SIZE (NRF51822_FLASH_PAGES * NRF51_PAGE_SIZE)
#define NRF51822_SRAM_SIZE (NRF51822_SRAM_PAGES * NRF51_PAGE_SIZE)
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
@@ -81,15 +83,8 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
memory_region_init_rom(&s->flash, OBJECT(s), "nrf51.flash", s->flash_size,
&err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
&err);
if (err) {
error_propagate(errp, err);
return;
@@ -121,6 +116,29 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
qdev_get_gpio_in(DEVICE(&s->cpu),
BASE_TO_IRQ(NRF51_RNG_BASE)));
/* UICR, FICR, NVMC, FLASH */
object_property_set_uint(OBJECT(&s->nvm), s->flash_size, "flash-size",
&err);
if (err) {
error_propagate(errp, err);
return;
}
object_property_set_bool(OBJECT(&s->nvm), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 0);
memory_region_add_subregion_overlap(&s->container, NRF51_NVMC_BASE, mr, 0);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 1);
memory_region_add_subregion_overlap(&s->container, NRF51_FICR_BASE, mr, 0);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 2);
memory_region_add_subregion_overlap(&s->container, NRF51_UICR_BASE, mr, 0);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 3);
memory_region_add_subregion_overlap(&s->container, NRF51_FLASH_BASE, mr, 0);
/* GPIO */
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
if (err) {
@@ -158,8 +176,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
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",
NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
}
@@ -186,6 +202,8 @@ static void nrf51_soc_init(Object *obj)
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
TYPE_NRF51_RNG);
sysbus_init_child_obj(obj, "nvm", &s->nvm, sizeof(s->nvm), TYPE_NRF51_NVM);
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
TYPE_NRF51_GPIO);
+1 -2
View File
@@ -2274,8 +2274,7 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
Error *err = NULL;
int regionlen;
s->cpu = ARM_CPU(qemu_get_cpu(0));
/* The armv7m container object will have set our CPU pointer */
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
return;
+1
View File
@@ -69,6 +69,7 @@ obj-$(CONFIG_TZ_PPC) += tz-ppc.o
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_AUX) += auxbus.o
+134
View File
@@ -0,0 +1,134 @@
/*
* ARM SSE-200 CPU_IDENTITY register block
*
* Copyright (c) 2019 Linaro Limited
* Written by Peter Maydell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 or
* (at your option) any later version.
*/
/*
* This is a model of the "CPU_IDENTITY" register block which is part of the
* Arm SSE-200 and documented in
* 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
*
* It consists of one read-only CPUID register (set by QOM property), plus the
* usual ID registers.
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "trace.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
#include "hw/registerfields.h"
#include "hw/misc/armsse-cpuid.h"
REG32(CPUID, 0x0)
REG32(PID4, 0xfd0)
REG32(PID5, 0xfd4)
REG32(PID6, 0xfd8)
REG32(PID7, 0xfdc)
REG32(PID0, 0xfe0)
REG32(PID1, 0xfe4)
REG32(PID2, 0xfe8)
REG32(PID3, 0xfec)
REG32(CID0, 0xff0)
REG32(CID1, 0xff4)
REG32(CID2, 0xff8)
REG32(CID3, 0xffc)
/* PID/CID values */
static const int sysinfo_id[] = {
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
static uint64_t armsse_cpuid_read(void *opaque, hwaddr offset,
unsigned size)
{
ARMSSECPUID *s = ARMSSE_CPUID(opaque);
uint64_t r;
switch (offset) {
case A_CPUID:
r = s->cpuid;
break;
case A_PID4 ... A_CID3:
r = sysinfo_id[(offset - A_PID4) / 4];
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"SSE CPU_IDENTITY read: bad offset 0x%x\n", (int)offset);
r = 0;
break;
}
trace_armsse_cpuid_read(offset, r, size);
return r;
}
static void armsse_cpuid_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
trace_armsse_cpuid_write(offset, value, size);
qemu_log_mask(LOG_GUEST_ERROR,
"SSE CPU_IDENTITY: write to RO offset 0x%x\n", (int)offset);
}
static const MemoryRegionOps armsse_cpuid_ops = {
.read = armsse_cpuid_read,
.write = armsse_cpuid_write,
.endianness = DEVICE_LITTLE_ENDIAN,
/* byte/halfword accesses are just zero-padded on reads and writes */
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
};
static Property armsse_cpuid_props[] = {
DEFINE_PROP_UINT32("CPUID", ARMSSECPUID, cpuid, 0),
DEFINE_PROP_END_OF_LIST()
};
static void armsse_cpuid_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ARMSSECPUID *s = ARMSSE_CPUID(obj);
memory_region_init_io(&s->iomem, obj, &armsse_cpuid_ops,
s, "armsse-cpuid", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
}
static void armsse_cpuid_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
/*
* This device has no guest-modifiable state and so it
* does not need a reset function or VMState.
*/
dc->props = armsse_cpuid_props;
}
static const TypeInfo armsse_cpuid_info = {
.name = TYPE_ARMSSE_CPUID,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMSSECPUID),
.instance_init = armsse_cpuid_init,
.class_init = armsse_cpuid_class_init,
};
static void armsse_cpuid_register_types(void)
{
type_register_static(&armsse_cpuid_info);
}
type_init(armsse_cpuid_register_types);
+3 -2
View File
@@ -600,7 +600,7 @@ static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
{
IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
}
static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
@@ -686,7 +686,8 @@ static void iotkit_secctl_init(Object *obj)
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
IOTS_NUM_MPC);
qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
"mpcexp_status", IOTS_NUM_EXP_MPC);
+13 -2
View File
@@ -51,15 +51,16 @@ static const int sysinfo_id[] = {
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
unsigned size)
{
IoTKitSysInfo *s = IOTKIT_SYSINFO(opaque);
uint64_t r;
switch (offset) {
case A_SYS_VERSION:
r = 0x41743;
r = s->sys_version;
break;
case A_SYS_CONFIG:
r = 0x31;
r = s->sys_config;
break;
case A_PID4 ... A_CID3:
r = sysinfo_id[(offset - A_PID4) / 4];
@@ -94,6 +95,12 @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
.valid.max_access_size = 4,
};
static Property iotkit_sysinfo_props[] = {
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
DEFINE_PROP_END_OF_LIST()
};
static void iotkit_sysinfo_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -106,10 +113,14 @@ static void iotkit_sysinfo_init(Object *obj)
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
/*
* This device has no guest-modifiable state and so it
* does not need a reset function or VMState.
*/
dc->props = iotkit_sysinfo_props;
}
static const TypeInfo iotkit_sysinfo_info = {
+4
View File
@@ -132,3 +132,7 @@ iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysI
iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
# hw/misc/armsse-cpuid.c
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+1
View File
@@ -5,3 +5,4 @@ common-obj-y += fw_cfg.o
common-obj-y += chrp_nvram.o
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
obj-$(CONFIG_PSERIES) += spapr_nvram.o
obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o
+388
View File
@@ -0,0 +1,388 @@
/*
* Nordic Semiconductor nRF51 non-volatile memory
*
* It provides an interface to erase regions in flash memory.
* Furthermore it provides the user and factory information registers.
*
* Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
*
* See nRF51 reference manual and product sheet sections:
* + Non-Volatile Memory Controller (NVMC)
* + Factory Information Configuration Registers (FICR)
* + User Information Configuration Registers (UICR)
*
* Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "exec/address-spaces.h"
#include "hw/arm/nrf51.h"
#include "hw/nvram/nrf51_nvm.h"
/*
* FICR Registers Assignments
* CODEPAGESIZE 0x010
* CODESIZE 0x014
* CLENR0 0x028
* PPFC 0x02C
* NUMRAMBLOCK 0x034
* SIZERAMBLOCKS 0x038
* SIZERAMBLOCK[0] 0x038
* SIZERAMBLOCK[1] 0x03C
* SIZERAMBLOCK[2] 0x040
* SIZERAMBLOCK[3] 0x044
* CONFIGID 0x05C
* DEVICEID[0] 0x060
* DEVICEID[1] 0x064
* ER[0] 0x080
* ER[1] 0x084
* ER[2] 0x088
* ER[3] 0x08C
* IR[0] 0x090
* IR[1] 0x094
* IR[2] 0x098
* IR[3] 0x09C
* DEVICEADDRTYPE 0x0A0
* DEVICEADDR[0] 0x0A4
* DEVICEADDR[1] 0x0A8
* OVERRIDEEN 0x0AC
* NRF_1MBIT[0] 0x0B0
* NRF_1MBIT[1] 0x0B4
* NRF_1MBIT[2] 0x0B8
* NRF_1MBIT[3] 0x0BC
* NRF_1MBIT[4] 0x0C0
* BLE_1MBIT[0] 0x0EC
* BLE_1MBIT[1] 0x0F0
* BLE_1MBIT[2] 0x0F4
* BLE_1MBIT[3] 0x0F8
* BLE_1MBIT[4] 0x0FC
*/
static const uint32_t ficr_content[64] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000400,
0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, 0x00002000,
0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
0x12345678, 0x9ABCDEF1, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
};
static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size)
{
assert(offset < sizeof(ficr_content));
return ficr_content[offset / 4];
}
static void ficr_write(void *opaque, hwaddr offset, uint64_t value,
unsigned int size)
{
/* Intentionally do nothing */
}
static const MemoryRegionOps ficr_ops = {
.read = ficr_read,
.write = ficr_write,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN
};
/*
* UICR Registers Assignments
* CLENR0 0x000
* RBPCONF 0x004
* XTALFREQ 0x008
* FWID 0x010
* BOOTLOADERADDR 0x014
* NRFFW[0] 0x014
* NRFFW[1] 0x018
* NRFFW[2] 0x01C
* NRFFW[3] 0x020
* NRFFW[4] 0x024
* NRFFW[5] 0x028
* NRFFW[6] 0x02C
* NRFFW[7] 0x030
* NRFFW[8] 0x034
* NRFFW[9] 0x038
* NRFFW[10] 0x03C
* NRFFW[11] 0x040
* NRFFW[12] 0x044
* NRFFW[13] 0x048
* NRFFW[14] 0x04C
* NRFHW[0] 0x050
* NRFHW[1] 0x054
* NRFHW[2] 0x058
* NRFHW[3] 0x05C
* NRFHW[4] 0x060
* NRFHW[5] 0x064
* NRFHW[6] 0x068
* NRFHW[7] 0x06C
* NRFHW[8] 0x070
* NRFHW[9] 0x074
* NRFHW[10] 0x078
* NRFHW[11] 0x07C
* CUSTOMER[0] 0x080
* CUSTOMER[1] 0x084
* CUSTOMER[2] 0x088
* CUSTOMER[3] 0x08C
* CUSTOMER[4] 0x090
* CUSTOMER[5] 0x094
* CUSTOMER[6] 0x098
* CUSTOMER[7] 0x09C
* CUSTOMER[8] 0x0A0
* CUSTOMER[9] 0x0A4
* CUSTOMER[10] 0x0A8
* CUSTOMER[11] 0x0AC
* CUSTOMER[12] 0x0B0
* CUSTOMER[13] 0x0B4
* CUSTOMER[14] 0x0B8
* CUSTOMER[15] 0x0BC
* CUSTOMER[16] 0x0C0
* CUSTOMER[17] 0x0C4
* CUSTOMER[18] 0x0C8
* CUSTOMER[19] 0x0CC
* CUSTOMER[20] 0x0D0
* CUSTOMER[21] 0x0D4
* CUSTOMER[22] 0x0D8
* CUSTOMER[23] 0x0DC
* CUSTOMER[24] 0x0E0
* CUSTOMER[25] 0x0E4
* CUSTOMER[26] 0x0E8
* CUSTOMER[27] 0x0EC
* CUSTOMER[28] 0x0F0
* CUSTOMER[29] 0x0F4
* CUSTOMER[30] 0x0F8
* CUSTOMER[31] 0x0FC
*/
static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size)
{
NRF51NVMState *s = NRF51_NVM(opaque);
assert(offset < sizeof(s->uicr_content));
return s->uicr_content[offset / 4];
}
static void uicr_write(void *opaque, hwaddr offset, uint64_t value,
unsigned int size)
{
NRF51NVMState *s = NRF51_NVM(opaque);
assert(offset < sizeof(s->uicr_content));
s->uicr_content[offset / 4] = value;
}
static const MemoryRegionOps uicr_ops = {
.read = uicr_read,
.write = uicr_write,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN
};
static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size)
{
NRF51NVMState *s = NRF51_NVM(opaque);
uint64_t r = 0;
switch (offset) {
case NRF51_NVMC_READY:
r = NRF51_NVMC_READY_READY;
break;
case NRF51_NVMC_CONFIG:
r = s->config;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
break;
}
return r;
}
static void io_write(void *opaque, hwaddr offset, uint64_t value,
unsigned int size)
{
NRF51NVMState *s = NRF51_NVM(opaque);
switch (offset) {
case NRF51_NVMC_CONFIG:
s->config = value & NRF51_NVMC_CONFIG_MASK;
break;
case NRF51_NVMC_ERASEPCR0:
case NRF51_NVMC_ERASEPCR1:
if (s->config & NRF51_NVMC_CONFIG_EEN) {
/* Mask in-page sub address */
value &= ~(NRF51_PAGE_SIZE - 1);
if (value <= (s->flash_size - NRF51_PAGE_SIZE)) {
memset(s->storage + value, 0xFF, NRF51_PAGE_SIZE);
memory_region_flush_rom_device(&s->flash, value,
NRF51_PAGE_SIZE);
}
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Flash erase at 0x%" HWADDR_PRIx" while flash not erasable.\n",
__func__, offset);
}
break;
case NRF51_NVMC_ERASEALL:
if (value == NRF51_NVMC_ERASE) {
if (s->config & NRF51_NVMC_CONFIG_EEN) {
memset(s->storage, 0xFF, s->flash_size);
memory_region_flush_rom_device(&s->flash, 0, s->flash_size);
memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash not erasable.\n",
__func__);
}
}
break;
case NRF51_NVMC_ERASEUICR:
if (value == NRF51_NVMC_ERASE) {
memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, offset);
}
}
static const MemoryRegionOps io_ops = {
.read = io_read,
.write = io_write,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void flash_write(void *opaque, hwaddr offset, uint64_t value,
unsigned int size)
{
NRF51NVMState *s = NRF51_NVM(opaque);
if (s->config & NRF51_NVMC_CONFIG_WEN) {
uint32_t oldval;
assert(offset + size <= s->flash_size);
/* NOR Flash only allows bits to be flipped from 1's to 0's on write */
oldval = ldl_le_p(s->storage + offset);
oldval &= value;
stl_le_p(s->storage + offset, oldval);
memory_region_flush_rom_device(&s->flash, offset, size);
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Flash write 0x%" HWADDR_PRIx" while flash not writable.\n",
__func__, offset);
}
}
static const MemoryRegionOps flash_ops = {
.write = flash_write,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void nrf51_nvm_init(Object *obj)
{
NRF51NVMState *s = NRF51_NVM(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->mmio, obj, &io_ops, s, "nrf51_soc.nvmc",
NRF51_NVMC_SIZE);
sysbus_init_mmio(sbd, &s->mmio);
memory_region_init_io(&s->ficr, obj, &ficr_ops, s, "nrf51_soc.ficr",
sizeof(ficr_content));
sysbus_init_mmio(sbd, &s->ficr);
memory_region_init_io(&s->uicr, obj, &uicr_ops, s, "nrf51_soc.uicr",
sizeof(s->uicr_content));
sysbus_init_mmio(sbd, &s->uicr);
}
static void nrf51_nvm_realize(DeviceState *dev, Error **errp)
{
NRF51NVMState *s = NRF51_NVM(dev);
Error *err = NULL;
memory_region_init_rom_device(&s->flash, OBJECT(dev), &flash_ops, s,
"nrf51_soc.flash", s->flash_size, &err);
if (err) {
error_propagate(errp, err);
return;
}
s->storage = memory_region_get_ram_ptr(&s->flash);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->flash);
}
static void nrf51_nvm_reset(DeviceState *dev)
{
NRF51NVMState *s = NRF51_NVM(dev);
s->config = 0x00;
memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
}
static Property nrf51_nvm_properties[] = {
DEFINE_PROP_UINT32("flash-size", NRF51NVMState, flash_size, 0x40000),
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_nvm = {
.name = "nrf51_soc.nvm",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(uicr_content, NRF51NVMState,
NRF51_UICR_FIXTURE_SIZE),
VMSTATE_UINT32(config, NRF51NVMState),
VMSTATE_END_OF_LIST()
}
};
static void nrf51_nvm_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->props = nrf51_nvm_properties;
dc->vmsd = &vmstate_nvm;
dc->realize = nrf51_nvm_realize;
dc->reset = nrf51_nvm_reset;
}
static const TypeInfo nrf51_nvm_info = {
.name = TYPE_NRF51_NVM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(NRF51NVMState),
.instance_init = nrf51_nvm_init,
.class_init = nrf51_nvm_class_init
};
static void nrf51_nvm_register_types(void)
{
type_register_static(&nrf51_nvm_info);
}
type_init(nrf51_nvm_register_types)
@@ -1,5 +1,5 @@
/*
* ARM IoT Kit
* ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
*
* Copyright (c) 2018 Linaro Limited
* Written by Peter Maydell
@@ -9,9 +9,16 @@
* (at your option) any later version.
*/
/* This is a model of the Arm IoT Kit which is documented in
/*
* This is a model of the Arm "Subsystems for Embedded" family of
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
* SSE-200. Currently we model:
* - the Arm IoT Kit which is documented in
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
* It contains:
* - the SSE-200 which is documented in
* 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
*
* The IoTKit contains:
* a Cortex-M33
* the IDAU
* some timers and watchdogs
@@ -20,14 +27,29 @@
* a security controller
* a bus fabric which arranges that some parts of the address
* space are secure and non-secure aliases of each other
* The SSE-200 additionally contains:
* a second Cortex-M33
* two Message Handling Units (MHUs)
* an optional CryptoCell (which we do not model)
* more SRAM banks with associated MPCs
* multiple Power Policy Units (PPUs)
* a control interface for an icache for each CPU
* per-CPU identity and control register blocks
*
* QEMU interface:
* + QOM property "memory" is a MemoryRegion containing the devices provided
* by the board model.
* + QOM property "MAINCLK" is the frequency of the main system clock
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
* are wired to the NVIC lines 32 .. n+32
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
* (In hardware, the SSE-200 permits the number of expansion interrupts
* for the two CPUs to be configured separately, but we restrict it to
* being the same for both, to avoid having to have separate Property
* lists for different variants. This restriction can be relaxed later
* if necessary.)
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
* which are wired to its NVIC lines 32 .. n+32
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
* CPU 1, which are wired to its NVIC lines 32 .. n+32
* + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
* bus master devices in the board model to make transactions into
* all the devices and memory areas in the IoTKit
@@ -55,8 +77,8 @@
* + named GPIO outputs mscexp_ns[0..15]
*/
#ifndef IOTKIT_H
#define IOTKIT_H
#ifndef ARMSSE_H
#define ARMSSE_H
#include "hw/sysbus.h"
#include "hw/arm/armv7m.h"
@@ -68,11 +90,22 @@
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "hw/misc/iotkit-sysctl.h"
#include "hw/misc/iotkit-sysinfo.h"
#include "hw/misc/armsse-cpuid.h"
#include "hw/misc/unimp.h"
#include "hw/or-irq.h"
#include "hw/core/split-irq.h"
#include "hw/cpu/cluster.h"
#define TYPE_ARMSSE "arm-sse"
#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
/*
* These type names are for specific IoTKit subsystems; other than
* instantiating them, code using these devices should always handle
* them via the ARMSSE base class, so they have no IOTKIT() etc macros.
*/
#define TYPE_IOTKIT "iotkit"
#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
#define TYPE_SSE200 "sse-200"
/* We have an IRQ splitter and an OR gate input for each external PPC
* and the 2 internal PPCs
@@ -80,16 +113,34 @@
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
typedef struct IoTKit {
#define MAX_SRAM_BANKS 4
#if MAX_SRAM_BANKS > IOTS_NUM_MPC
#error Too many SRAM banks
#endif
#define SSE_MAX_CPUS 2
/* These define what each PPU in the ppu[] index is for */
#define CPU0CORE_PPU 0
#define CPU1CORE_PPU 1
#define DBG_PPU 2
#define RAM0_PPU 3
#define RAM1_PPU 4
#define RAM2_PPU 5
#define RAM3_PPU 6
#define NUM_PPUS 7
typedef struct ARMSSE {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
ARMv7MState armv7m;
ARMv7MState armv7m[SSE_MAX_CPUS];
CPUClusterState cluster[SSE_MAX_CPUS];
IoTKitSecCtl secctl;
TZPPC apb_ppc0;
TZPPC apb_ppc1;
TZMPC mpc;
TZMPC mpc[IOTS_NUM_MPC];
CMSDKAPBTIMER timer0;
CMSDKAPBTIMER timer1;
CMSDKAPBTIMER s32ktimer;
@@ -100,6 +151,8 @@ typedef struct IoTKit {
qemu_or_irq mpc_irq_orgate;
qemu_or_irq nmi_orgate;
SplitIRQ cpu_irq_splitter[32];
CMSDKAPBDualTimer dualtimer;
CMSDKAPBWatchdog s32kwatchdog;
@@ -109,13 +162,30 @@ typedef struct IoTKit {
IoTKitSysCtl sysctl;
IoTKitSysCtl sysinfo;
UnimplementedDeviceState mhu[2];
UnimplementedDeviceState ppu[NUM_PPUS];
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
ARMSSECPUID cpuid[SSE_MAX_CPUS];
/*
* 'container' holds all devices seen by all CPUs.
* 'cpu_container[i]' is the view that CPU i has: this has the
* per-CPU devices of that CPU, plus as the background 'container'
* (or an alias of it, since we can only use it directly once).
* container_alias[i] is the alias of 'container' used by CPU i+1;
* CPU 0 can use 'container' directly.
*/
MemoryRegion container;
MemoryRegion container_alias[SSE_MAX_CPUS - 1];
MemoryRegion cpu_container[SSE_MAX_CPUS];
MemoryRegion alias1;
MemoryRegion alias2;
MemoryRegion alias3;
MemoryRegion sram0;
MemoryRegion sram[MAX_SRAM_BANKS];
qemu_irq *exp_irqs;
qemu_irq *exp_irqs[SSE_MAX_CPUS];
qemu_irq ppc0_irq;
qemu_irq ppc1_irq;
qemu_irq sec_resp_cfg;
@@ -131,6 +201,19 @@ typedef struct IoTKit {
MemoryRegion *board_memory;
uint32_t exp_numirq;
uint32_t mainclk_frq;
} IoTKit;
uint32_t sram_addr_width;
} ARMSSE;
typedef struct ARMSSEInfo ARMSSEInfo;
typedef struct ARMSSEClass {
DeviceClass parent_class;
const ARMSSEInfo *info;
} ARMSSEClass;
#define ARMSSE_CLASS(klass) \
OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE)
#define ARMSSE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE)
#endif
+1
View File
@@ -65,6 +65,7 @@ typedef struct ARMv7MState {
Object *idau;
uint32_t init_svtor;
bool enable_bitband;
bool start_powered_off;
} ARMv7MState;
#endif

Some files were not shown because too many files have changed in this diff Show More