aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/system/arm/emulation.rst2
-rw-r--r--hw/arm/armsse.c16
-rw-r--r--hw/arm/armv7m.c21
-rw-r--r--hw/arm/fsl-imx6ul.c174
-rw-r--r--hw/arm/fsl-imx7.c201
-rw-r--r--hw/arm/mps2-tz.c29
-rw-r--r--hw/misc/imx7_src.c276
-rw-r--r--hw/misc/meson.build1
-rw-r--r--hw/misc/trace-events4
-rw-r--r--hw/rtc/aspeed_rtc.c5
-rw-r--r--hw/rtc/m48t59.c2
-rw-r--r--hw/rtc/twl92230.c4
-rw-r--r--include/hw/arm/armsse.h5
-rw-r--r--include/hw/arm/armv7m.h8
-rw-r--r--include/hw/arm/fsl-imx6ul.h136
-rw-r--r--include/hw/arm/fsl-imx7.h334
-rw-r--r--include/hw/misc/imx7_src.h66
-rw-r--r--include/hw/rtc/aspeed_rtc.h2
-rw-r--r--include/sysemu/rtc.h4
-rw-r--r--softmmu/rtc.c4
-rw-r--r--target/arm/cpregs.h2
-rw-r--r--target/arm/cpu.c205
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/helper.c15
-rw-r--r--target/arm/internals.h6
-rw-r--r--target/arm/tcg/cpu32.c2
-rw-r--r--target/arm/tcg/cpu64.c102
-rw-r--r--target/arm/tcg/helper-a64.c9
-rw-r--r--target/arm/tcg/mte_helper.c90
-rw-r--r--target/arm/tcg/translate-a64.c5
-rw-r--r--target/arm/tcg/translate.h2
31 files changed, 1379 insertions, 358 deletions
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index bdafc68819..2e6a7c8961 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -14,6 +14,7 @@ the following architecture extensions:
- FEAT_BBM at level 2 (Translation table break-before-make levels)
- FEAT_BF16 (AArch64 BFloat16 instructions)
- FEAT_BTI (Branch Target Identification)
+- FEAT_CRC32 (CRC32 instructions)
- FEAT_CSV2 (Cache speculation variant 2)
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
@@ -40,6 +41,7 @@ the following architecture extensions:
- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
- FEAT_HCX (Support for the HCRX_EL2 register)
- FEAT_HPDS (Hierarchical permission disables)
+- FEAT_HPDS2 (Translation table page-based hardware attributes)
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
- FEAT_IDST (ID space trap handling)
- FEAT_IESB (Implicit error synchronization event)
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 0202bad787..11cd08b6c1 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -85,6 +85,8 @@ static Property iotkit_properties[] = {
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
DEFINE_PROP_END_OF_LIST()
};
@@ -98,6 +100,10 @@ static Property sse200_properties[] = {
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], false),
DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE, cpu_fpu[1], true),
DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE, cpu_dsp[1], true),
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
+ DEFINE_PROP_UINT32("CPU1_MPU_NS", ARMSSE, cpu_mpu_ns[1], 8),
+ DEFINE_PROP_UINT32("CPU1_MPU_S", ARMSSE, cpu_mpu_s[1], 8),
DEFINE_PROP_END_OF_LIST()
};
@@ -109,6 +115,8 @@ static Property sse300_properties[] = {
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
DEFINE_PROP_END_OF_LIST()
};
@@ -1029,6 +1037,14 @@ static void armsse_realize(DeviceState *dev, Error **errp)
return;
}
}
+ if (!object_property_set_uint(cpuobj, "mpu-ns-regions",
+ s->cpu_mpu_ns[i], errp)) {
+ return;
+ }
+ if (!object_property_set_uint(cpuobj, "mpu-s-regions",
+ s->cpu_mpu_s[i], errp)) {
+ return;
+ }
if (i > 0) {
memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 50a9507c0b..bf173b10b8 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -335,6 +335,25 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
}
/*
+ * Real M-profile hardware can be configured with a different number of
+ * MPU regions for Secure vs NonSecure. QEMU's CPU implementation doesn't
+ * support that yet, so catch attempts to select that.
+ */
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
+ s->mpu_ns_regions != s->mpu_s_regions) {
+ error_setg(errp,
+ "mpu-ns-regions and mpu-s-regions properties must have the same value");
+ return;
+ }
+ if (s->mpu_ns_regions != UINT_MAX &&
+ object_property_find(OBJECT(s->cpu), "pmsav7-dregion")) {
+ if (!object_property_set_uint(OBJECT(s->cpu), "pmsav7-dregion",
+ s->mpu_ns_regions, errp)) {
+ return;
+ }
+ }
+
+ /*
* 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.
*/
@@ -530,6 +549,8 @@ static Property armv7m_properties[] = {
false),
DEFINE_PROP_BOOL("vfp", ARMv7MState, vfp, true),
DEFINE_PROP_BOOL("dsp", ARMv7MState, dsp, true),
+ DEFINE_PROP_UINT32("mpu-ns-regions", ARMv7MState, mpu_ns_regions, UINT_MAX),
+ DEFINE_PROP_UINT32("mpu-s-regions", ARMv7MState, mpu_s_regions, UINT_MAX),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 2189dcbb72..e37b69a5e1 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -64,12 +64,7 @@ static void fsl_imx6ul_init(Object *obj)
object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
/*
- * GPR
- */
- object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR);
-
- /*
- * GPIOs 1 to 5
+ * GPIOs
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
snprintf(name, NAME_SIZE, "gpio%d", i);
@@ -77,7 +72,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * GPT 1, 2
+ * GPTs
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
snprintf(name, NAME_SIZE, "gpt%d", i);
@@ -85,7 +80,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * EPIT 1, 2
+ * EPITs
*/
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
snprintf(name, NAME_SIZE, "epit%d", i + 1);
@@ -93,7 +88,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * eCSPI
+ * eCSPIs
*/
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
snprintf(name, NAME_SIZE, "spi%d", i + 1);
@@ -101,7 +96,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * I2C
+ * I2Cs
*/
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
snprintf(name, NAME_SIZE, "i2c%d", i + 1);
@@ -109,7 +104,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * UART
+ * UARTs
*/
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
snprintf(name, NAME_SIZE, "uart%d", i);
@@ -117,25 +112,31 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * Ethernet
+ * Ethernets
*/
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
snprintf(name, NAME_SIZE, "eth%d", i);
object_initialize_child(obj, name, &s->eth[i], TYPE_IMX_ENET);
}
- /* USB */
+ /*
+ * USB PHYs
+ */
for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
snprintf(name, NAME_SIZE, "usbphy%d", i);
object_initialize_child(obj, name, &s->usbphy[i], TYPE_IMX_USBPHY);
}
+
+ /*
+ * USBs
+ */
for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
snprintf(name, NAME_SIZE, "usb%d", i);
object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA);
}
/*
- * SDHCI
+ * SDHCIs
*/
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
snprintf(name, NAME_SIZE, "usdhc%d", i);
@@ -143,7 +144,7 @@ static void fsl_imx6ul_init(Object *obj)
}
/*
- * Watchdog
+ * Watchdogs
*/
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
snprintf(name, NAME_SIZE, "wdt%d", i);
@@ -189,10 +190,10 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
* A7MPCORE DAP
*/
create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR,
- 0x100000);
+ FSL_IMX6UL_A7MPCORE_DAP_SIZE);
/*
- * GPT 1, 2
+ * GPTs
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
static const hwaddr FSL_IMX6UL_GPTn_ADDR[FSL_IMX6UL_NUM_GPTS] = {
@@ -217,7 +218,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * EPIT 1, 2
+ * EPITs
*/
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
static const hwaddr FSL_IMX6UL_EPITn_ADDR[FSL_IMX6UL_NUM_EPITS] = {
@@ -242,7 +243,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * GPIO
+ * GPIOs
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
static const hwaddr FSL_IMX6UL_GPIOn_ADDR[FSL_IMX6UL_NUM_GPIOS] = {
@@ -284,17 +285,12 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * IOMUXC and IOMUXC_GPR
+ * IOMUXC
*/
- for (i = 0; i < 1; i++) {
- static const hwaddr FSL_IMX6UL_IOMUXCn_ADDR[FSL_IMX6UL_NUM_IOMUXCS] = {
- FSL_IMX6UL_IOMUXC_ADDR,
- FSL_IMX6UL_IOMUXC_GPR_ADDR,
- };
-
- snprintf(name, NAME_SIZE, "iomuxc%d", i);
- create_unimplemented_device(name, FSL_IMX6UL_IOMUXCn_ADDR[i], 0x4000);
- }
+ create_unimplemented_device("iomuxc", FSL_IMX6UL_IOMUXC_ADDR,
+ FSL_IMX6UL_IOMUXC_SIZE);
+ create_unimplemented_device("iomuxc_gpr", FSL_IMX6UL_IOMUXC_GPR_ADDR,
+ FSL_IMX6UL_IOMUXC_GPR_SIZE);
/*
* CCM
@@ -314,7 +310,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR);
- /* Initialize all ECSPI */
+ /*
+ * ECSPIs
+ */
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
static const hwaddr FSL_IMX6UL_SPIn_ADDR[FSL_IMX6UL_NUM_ECSPIS] = {
FSL_IMX6UL_ECSPI1_ADDR,
@@ -342,7 +340,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * I2C
+ * I2Cs
*/
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
static const hwaddr FSL_IMX6UL_I2Cn_ADDR[FSL_IMX6UL_NUM_I2CS] = {
@@ -368,7 +366,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * UART
+ * UARTs
*/
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
static const hwaddr FSL_IMX6UL_UARTn_ADDR[FSL_IMX6UL_NUM_UARTS] = {
@@ -406,7 +404,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * Ethernet
+ * Ethernets
*
* We must use two loops since phy_connected affects the other interface
* and we have to set all properties before calling sysbus_realize().
@@ -459,28 +457,45 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
}
- /* USB */
+ /*
+ * USB PHYs
+ */
for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
+ static const hwaddr
+ FSL_IMX6UL_USB_PHYn_ADDR[FSL_IMX6UL_NUM_USB_PHYS] = {
+ FSL_IMX6UL_USBPHY1_ADDR,
+ FSL_IMX6UL_USBPHY2_ADDR,
+ };
+
sysbus_realize(SYS_BUS_DEVICE(&s->usbphy[i]), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0,
- FSL_IMX6UL_USBPHY1_ADDR + i * 0x1000);
+ FSL_IMX6UL_USB_PHYn_ADDR[i]);
}
+ /*
+ * USBs
+ */
for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
+ static const hwaddr FSL_IMX6UL_USB02_USBn_ADDR[FSL_IMX6UL_NUM_USBS] = {
+ FSL_IMX6UL_USBO2_USB1_ADDR,
+ FSL_IMX6UL_USBO2_USB2_ADDR,
+ };
+
static const int FSL_IMX6UL_USBn_IRQ[] = {
FSL_IMX6UL_USB1_IRQ,
FSL_IMX6UL_USB2_IRQ,
};
+
sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
- FSL_IMX6UL_USBO2_USB_ADDR + i * 0x200);
+ FSL_IMX6UL_USB02_USBn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_USBn_IRQ[i]));
}
/*
- * USDHC
+ * USDHCs
*/
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
static const hwaddr FSL_IMX6UL_USDHCn_ADDR[FSL_IMX6UL_NUM_USDHCS] = {
@@ -512,7 +527,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR);
/*
- * Watchdog
+ * Watchdogs
*/
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
static const hwaddr FSL_IMX6UL_WDOGn_ADDR[FSL_IMX6UL_NUM_WDTS] = {
@@ -520,6 +535,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
FSL_IMX6UL_WDOG2_ADDR,
FSL_IMX6UL_WDOG3_ADDR,
};
+
static const int FSL_IMX6UL_WDOGn_IRQ[FSL_IMX6UL_NUM_WDTS] = {
FSL_IMX6UL_WDOG1_IRQ,
FSL_IMX6UL_WDOG2_IRQ,
@@ -538,41 +554,65 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
}
/*
- * GPR
- */
- sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR);
-
- /*
* SDMA
*/
- create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
+ create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR,
+ FSL_IMX6UL_SDMA_SIZE);
/*
- * SAI (Audio SSI (Synchronous Serial Interface))
+ * SAIs (Audio SSI (Synchronous Serial Interface))
*/
- create_unimplemented_device("sai1", FSL_IMX6UL_SAI1_ADDR, 0x4000);
- create_unimplemented_device("sai2", FSL_IMX6UL_SAI2_ADDR, 0x4000);
- create_unimplemented_device("sai3", FSL_IMX6UL_SAI3_ADDR, 0x4000);
+ for (i = 0; i < FSL_IMX6UL_NUM_SAIS; i++) {
+ static const hwaddr FSL_IMX6UL_SAIn_ADDR[FSL_IMX6UL_NUM_SAIS] = {
+ FSL_IMX6UL_SAI1_ADDR,
+ FSL_IMX6UL_SAI2_ADDR,
+ FSL_IMX6UL_SAI3_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "sai%d", i);
+ create_unimplemented_device(name, FSL_IMX6UL_SAIn_ADDR[i],
+ FSL_IMX6UL_SAIn_SIZE);
+ }
/*
- * PWM
+ * PWMs
*/
- create_unimplemented_device("pwm1", FSL_IMX6UL_PWM1_ADDR, 0x4000);
- create_unimplemented_device("pwm2", FSL_IMX6UL_PWM2_ADDR, 0x4000);
- create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000);
- create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000);
+ for (i = 0; i < FSL_IMX6UL_NUM_PWMS; i++) {
+ static const hwaddr FSL_IMX6UL_PWMn_ADDR[FSL_IMX6UL_NUM_PWMS] = {
+ FSL_IMX6UL_PWM1_ADDR,
+ FSL_IMX6UL_PWM2_ADDR,
+ FSL_IMX6UL_PWM3_ADDR,
+ FSL_IMX6UL_PWM4_ADDR,
+ FSL_IMX6UL_PWM5_ADDR,
+ FSL_IMX6UL_PWM6_ADDR,
+ FSL_IMX6UL_PWM7_ADDR,
+ FSL_IMX6UL_PWM8_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "pwm%d", i);
+ create_unimplemented_device(name, FSL_IMX6UL_PWMn_ADDR[i],
+ FSL_IMX6UL_PWMn_SIZE);
+ }
/*
* Audio ASRC (asynchronous sample rate converter)
*/
- create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR, 0x4000);
+ create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR,
+ FSL_IMX6UL_ASRC_SIZE);
/*
- * CAN
+ * CANs
*/
- create_unimplemented_device("can1", FSL_IMX6UL_CAN1_ADDR, 0x4000);
- create_unimplemented_device("can2", FSL_IMX6UL_CAN2_ADDR, 0x4000);
+ for (i = 0; i < FSL_IMX6UL_NUM_CANS; i++) {
+ static const hwaddr FSL_IMX6UL_CANn_ADDR[FSL_IMX6UL_NUM_CANS] = {
+ FSL_IMX6UL_CAN1_ADDR,
+ FSL_IMX6UL_CAN2_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "can%d", i);
+ create_unimplemented_device(name, FSL_IMX6UL_CANn_ADDR[i],
+ FSL_IMX6UL_CANn_SIZE);
+ }
/*
* APHB_DMA
@@ -590,13 +630,27 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
};
snprintf(name, NAME_SIZE, "adc%d", i);
- create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i], 0x4000);
+ create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i],
+ FSL_IMX6UL_ADCn_SIZE);
}
/*
* LCD
*/
- create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR, 0x4000);
+ create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR,
+ FSL_IMX6UL_LCDIF_SIZE);
+
+ /*
+ * CSU
+ */
+ create_unimplemented_device("csu", FSL_IMX6UL_CSU_ADDR,
+ FSL_IMX6UL_CSU_SIZE);
+
+ /*
+ * TZASC
+ */
+ create_unimplemented_device("tzasc", FSL_IMX6UL_TZASC_ADDR,
+ FSL_IMX6UL_TZASC_SIZE);
/*
* ROM memory
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 9e41d4b677..474cfdc87c 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -36,6 +36,9 @@ static void fsl_imx7_init(Object *obj)
char name[NAME_SIZE];
int i;
+ /*
+ * CPUs
+ */
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) {
snprintf(name, NAME_SIZE, "cpu%d", i);
object_initialize_child(obj, name, &s->cpu[i],
@@ -49,7 +52,7 @@ static void fsl_imx7_init(Object *obj)
TYPE_A15MPCORE_PRIV);
/*
- * GPIOs 1 to 7
+ * GPIOs
*/
for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
snprintf(name, NAME_SIZE, "gpio%d", i);
@@ -57,7 +60,7 @@ static void fsl_imx7_init(Object *obj)
}
/*
- * GPT1, 2, 3, 4
+ * GPTs
*/
for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
snprintf(name, NAME_SIZE, "gpt%d", i);
@@ -79,19 +82,29 @@ static void fsl_imx7_init(Object *obj)
*/
object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2);
+ /*
+ * SRC
+ */
+ object_initialize_child(obj, "src", &s->src, TYPE_IMX7_SRC);
+
+ /*
+ * ECSPIs
+ */
for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
snprintf(name, NAME_SIZE, "spi%d", i + 1);
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
}
-
+ /*
+ * I2Cs
+ */
for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
snprintf(name, NAME_SIZE, "i2c%d", i + 1);
object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
}
/*
- * UART
+ * UARTs
*/
for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
snprintf(name, NAME_SIZE, "uart%d", i);
@@ -99,7 +112,7 @@ static void fsl_imx7_init(Object *obj)
}
/*
- * Ethernet
+ * Ethernets
*/
for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
snprintf(name, NAME_SIZE, "eth%d", i);
@@ -107,7 +120,7 @@ static void fsl_imx7_init(Object *obj)
}
/*
- * SDHCI
+ * SDHCIs
*/
for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
snprintf(name, NAME_SIZE, "usdhc%d", i);
@@ -120,7 +133,7 @@ static void fsl_imx7_init(Object *obj)
object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
/*
- * Watchdog
+ * Watchdogs
*/
for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
snprintf(name, NAME_SIZE, "wdt%d", i);
@@ -132,8 +145,14 @@ static void fsl_imx7_init(Object *obj)
*/
object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR);
+ /*
+ * PCIE
+ */
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+ /*
+ * USBs
+ */
for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
snprintf(name, NAME_SIZE, "usb%d", i);
object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA);
@@ -156,6 +175,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
return;
}
+ /*
+ * CPUs
+ */
for (i = 0; i < smp_cpus; i++) {
o = OBJECT(&s->cpu[i]);
@@ -206,10 +228,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
* A7MPCORE DAP
*/
create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR,
- 0x100000);
+ FSL_IMX7_A7MPCORE_DAP_SIZE);
/*
- * GPT1, 2, 3, 4
+ * GPTs
*/
for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = {
@@ -234,6 +256,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
FSL_IMX7_GPTn_IRQ[i]));
}
+ /*
+ * GPIOs
+ */
for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = {
FSL_IMX7_GPIO1_ADDR,
@@ -281,16 +306,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
/*
* IOMUXC and IOMUXC_LPSR
*/
- for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) {
- static const hwaddr FSL_IMX7_IOMUXCn_ADDR[FSL_IMX7_NUM_IOMUXCS] = {
- FSL_IMX7_IOMUXC_ADDR,
- FSL_IMX7_IOMUXC_LPSR_ADDR,
- };
-
- snprintf(name, NAME_SIZE, "iomuxc%d", i);
- create_unimplemented_device(name, FSL_IMX7_IOMUXCn_ADDR[i],
- FSL_IMX7_IOMUXCn_SIZE);
- }
+ create_unimplemented_device("iomuxc", FSL_IMX7_IOMUXC_ADDR,
+ FSL_IMX7_IOMUXC_SIZE);
+ create_unimplemented_device("iomuxc_lspr", FSL_IMX7_IOMUXC_LPSR_ADDR,
+ FSL_IMX7_IOMUXC_LPSR_SIZE);
/*
* CCM
@@ -310,7 +329,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR);
- /* Initialize all ECSPI */
+ /*
+ * ECSPIs
+ */
for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = {
FSL_IMX7_ECSPI1_ADDR,
@@ -335,6 +356,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
FSL_IMX7_SPIn_IRQ[i]));
}
+ /*
+ * I2Cs
+ */
for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = {
FSL_IMX7_I2C1_ADDR,
@@ -359,7 +383,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
}
/*
- * UART
+ * UARTs
*/
for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = {
@@ -394,7 +418,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
}
/*
- * Ethernet
+ * Ethernets
*
* We must use two loops since phy_connected affects the other interface
* and we have to set all properties before calling sysbus_realize().
@@ -434,7 +458,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
}
/*
- * USDHC
+ * USDHCs
*/
for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = {
@@ -464,15 +488,16 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
* SNVS
*/
sysbus_realize(SYS_BUS_DEVICE(&s->snvs), &error_abort);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_HP_ADDR);
/*
* SRC
*/
- create_unimplemented_device("src", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
+ sysbus_realize(SYS_BUS_DEVICE(&s->src), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX7_SRC_ADDR);
/*
- * Watchdog
+ * Watchdogs
*/
for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = {
@@ -509,25 +534,49 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE);
/*
- * PWM
+ * PWMs
*/
- create_unimplemented_device("pwm1", FSL_IMX7_PWM1_ADDR, FSL_IMX7_PWMn_SIZE);
- create_unimplemented_device("pwm2", FSL_IMX7_PWM2_ADDR, FSL_IMX7_PWMn_SIZE);
- create_unimplemented_device("pwm3", FSL_IMX7_PWM3_ADDR, FSL_IMX7_PWMn_SIZE);
- create_unimplemented_device("pwm4", FSL_IMX7_PWM4_ADDR, FSL_IMX7_PWMn_SIZE);
+ for (i = 0; i < FSL_IMX7_NUM_PWMS; i++) {
+ static const hwaddr FSL_IMX7_PWMn_ADDR[FSL_IMX7_NUM_PWMS] = {
+ FSL_IMX7_PWM1_ADDR,
+ FSL_IMX7_PWM2_ADDR,
+ FSL_IMX7_PWM3_ADDR,
+ FSL_IMX7_PWM4_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "pwm%d", i);
+ create_unimplemented_device(name, FSL_IMX7_PWMn_ADDR[i],
+ FSL_IMX7_PWMn_SIZE);
+ }
/*
- * CAN
+ * CANs
*/
- create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
- create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
+ for (i = 0; i < FSL_IMX7_NUM_CANS; i++) {
+ static const hwaddr FSL_IMX7_CANn_ADDR[FSL_IMX7_NUM_CANS] = {
+ FSL_IMX7_CAN1_ADDR,
+ FSL_IMX7_CAN2_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "can%d", i);
+ create_unimplemented_device(name, FSL_IMX7_CANn_ADDR[i],
+ FSL_IMX7_CANn_SIZE);
+ }
/*
- * SAI (Audio SSI (Synchronous Serial Interface))
+ * SAIs (Audio SSI (Synchronous Serial Interface))
*/
- create_unimplemented_device("sai1", FSL_IMX7_SAI1_ADDR, FSL_IMX7_SAIn_SIZE);
- create_unimplemented_device("sai2", FSL_IMX7_SAI2_ADDR, FSL_IMX7_SAIn_SIZE);
- create_unimplemented_device("sai2", FSL_IMX7_SAI3_ADDR, FSL_IMX7_SAIn_SIZE);
+ for (i = 0; i < FSL_IMX7_NUM_SAIS; i++) {
+ static const hwaddr FSL_IMX7_SAIn_ADDR[FSL_IMX7_NUM_SAIS] = {
+ FSL_IMX7_SAI1_ADDR,
+ FSL_IMX7_SAI2_ADDR,
+ FSL_IMX7_SAI3_ADDR,
+ };
+
+ snprintf(name, NAME_SIZE, "sai%d", i);
+ create_unimplemented_device(name, FSL_IMX7_SAIn_ADDR[i],
+ FSL_IMX7_SAIn_SIZE);
+ }
/*
* OCOTP
@@ -535,9 +584,15 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR,
FSL_IMX7_OCOTP_SIZE);
+ /*
+ * GPR
+ */
sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_IOMUXC_GPR_ADDR);
+ /*
+ * PCIE
+ */
sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
@@ -550,7 +605,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
-
+ /*
+ * USBs
+ */
for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = {
FSL_IMX7_USBMISC1_ADDR,
@@ -612,6 +669,70 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
*/
create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR,
FSL_IMX7_PCIE_PHY_SIZE);
+
+ /*
+ * CSU
+ */
+ create_unimplemented_device("csu", FSL_IMX7_CSU_ADDR,
+ FSL_IMX7_CSU_SIZE);
+
+ /*
+ * TZASC
+ */
+ create_unimplemented_device("tzasc", FSL_IMX7_TZASC_ADDR,
+ FSL_IMX7_TZASC_SIZE);
+
+ /*
+ * OCRAM memory
+ */
+ memory_region_init_ram(&s->ocram, NULL, "imx7.ocram",
+ FSL_IMX7_OCRAM_MEM_SIZE,
+ &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_MEM_ADDR,
+ &s->ocram);
+
+ /*
+ * OCRAM EPDC memory
+ */
+ memory_region_init_ram(&s->ocram_epdc, NULL, "imx7.ocram_epdc",
+ FSL_IMX7_OCRAM_EPDC_SIZE,
+ &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_EPDC_ADDR,
+ &s->ocram_epdc);
+
+ /*
+ * OCRAM PXP memory
+ */
+ memory_region_init_ram(&s->ocram_pxp, NULL, "imx7.ocram_pxp",
+ FSL_IMX7_OCRAM_PXP_SIZE,
+ &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_PXP_ADDR,
+ &s->ocram_pxp);
+
+ /*
+ * OCRAM_S memory
+ */
+ memory_region_init_ram(&s->ocram_s, NULL, "imx7.ocram_s",
+ FSL_IMX7_OCRAM_S_SIZE,
+ &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_S_ADDR,
+ &s->ocram_s);
+
+ /*
+ * ROM memory
+ */
+ memory_region_init_rom(&s->rom, OBJECT(dev), "imx7.rom",
+ FSL_IMX7_ROM_SIZE, &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_ROM_ADDR,
+ &s->rom);
+
+ /*
+ * CAAM memory
+ */
+ memory_region_init_rom(&s->caam, OBJECT(dev), "imx7.caam",
+ FSL_IMX7_CAAM_MEM_SIZE, &error_abort);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_CAAM_MEM_ADDR,
+ &s->caam);
}
static Property fsl_imx7_properties[] = {
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 5873107302..eae3639da2 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -124,6 +124,10 @@ struct MPS2TZMachineClass {
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
uint32_t init_svtor; /* init-svtor setting for SSE */
uint32_t sram_addr_width; /* SRAM_ADDR_WIDTH setting for SSE */
+ uint32_t cpu0_mpu_ns; /* CPU0_MPU_NS setting for SSE */
+ uint32_t cpu0_mpu_s; /* CPU0_MPU_S setting for SSE */
+ uint32_t cpu1_mpu_ns; /* CPU1_MPU_NS setting for SSE */
+ uint32_t cpu1_mpu_s; /* CPU1_MPU_S setting for SSE */
const RAMInfo *raminfo;
const char *armsse_type;
uint32_t boot_ram_size; /* size of ram at address 0; 0 == find in raminfo */
@@ -183,6 +187,9 @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
#define MPS3_DDR_SIZE (2 * GiB)
#endif
+/* For cpu{0,1}_mpu_{ns,s}, means "leave at SSE's default value" */
+#define MPU_REGION_DEFAULT UINT32_MAX
+
static const uint32_t an505_oscclk[] = {
40000000,
24580000,
@@ -828,6 +835,20 @@ static void mps2tz_common_init(MachineState *machine)
OBJECT(system_memory), &error_abort);
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
+ if (mmc->cpu0_mpu_ns != MPU_REGION_DEFAULT) {
+ qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_NS", mmc->cpu0_mpu_ns);
+ }
+ if (mmc->cpu0_mpu_s != MPU_REGION_DEFAULT) {
+ qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_S", mmc->cpu0_mpu_s);
+ }
+ if (object_property_find(OBJECT(iotkitdev), "CPU1_MPU_NS")) {
+ if (mmc->cpu1_mpu_ns != MPU_REGION_DEFAULT) {
+ qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_NS", mmc->cpu1_mpu_ns);
+ }
+ if (mmc->cpu1_mpu_s != MPU_REGION_DEFAULT) {
+ qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_S", mmc->cpu1_mpu_s);
+ }
+ }
qdev_prop_set_uint32(iotkitdev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
@@ -1256,10 +1277,17 @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
mc->init = mps2tz_common_init;
mc->reset = mps2_machine_reset;
iic->check = mps2_tz_idau_check;
+
+ /* Most machines leave these at the SSE defaults */
+ mmc->cpu0_mpu_ns = MPU_REGION_DEFAULT;
+ mmc->cpu0_mpu_s = MPU_REGION_DEFAULT;
+ mmc->cpu1_mpu_ns = MPU_REGION_DEFAULT;
+ mmc->cpu1_mpu_s = MPU_REGION_DEFAULT;
}
static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
@@ -1396,6 +1424,7 @@ static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
mmc->numirq = 96;
mmc->uart_overflow_irq = 48;
mmc->init_svtor = 0x00000000;
+ mmc->cpu0_mpu_s = mmc->cpu0_mpu_ns = 16;
mmc->sram_addr_width = 21;
mmc->raminfo = an547_raminfo;
mmc->armsse_type = TYPE_SSE300;
diff --git a/hw/misc/imx7_src.c b/hw/misc/imx7_src.c
new file mode 100644
index 0000000000..983251e86f
--- /dev/null
+++ b/hw/misc/imx7_src.c
@@ -0,0 +1,276 @@
+/*
+ * IMX7 System Reset Controller
+ *
+ * Copyright (c) 2023 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_src.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
+#include "target/arm/arm-powerctl.h"
+#include "hw/core/cpu.h"
+#include "hw/registerfields.h"
+
+#include "trace.h"
+
+static const char *imx7_src_reg_name(uint32_t reg)
+{
+ static char unknown[20];
+
+ switch (reg) {
+ case SRC_SCR:
+ return "SRC_SCR";
+ case SRC_A7RCR0:
+ return "SRC_A7RCR0";
+ case SRC_A7RCR1:
+ return "SRC_A7RCR1";
+ case SRC_M4RCR:
+ return "SRC_M4RCR";
+ case SRC_ERCR:
+ return "SRC_ERCR";
+ case SRC_HSICPHY_RCR:
+ return "SRC_HSICPHY_RCR";
+ case SRC_USBOPHY1_RCR:
+ return "SRC_USBOPHY1_RCR";
+ case SRC_USBOPHY2_RCR:
+ return "SRC_USBOPHY2_RCR";
+ case SRC_PCIEPHY_RCR:
+ return "SRC_PCIEPHY_RCR";
+ case SRC_SBMR1:
+ return "SRC_SBMR1";
+ case SRC_SRSR:
+ return "SRC_SRSR";
+ case SRC_SISR:
+ return "SRC_SISR";
+ case SRC_SIMR:
+ return "SRC_SIMR";
+ case SRC_SBMR2:
+ return "SRC_SBMR2";
+ case SRC_GPR1:
+ return "SRC_GPR1";
+ case SRC_GPR2:
+ return "SRC_GPR2";
+ case SRC_GPR3:
+ return "SRC_GPR3";
+ case SRC_GPR4:
+ return "SRC_GPR4";
+ case SRC_GPR5:
+ return "SRC_GPR5";
+ case SRC_GPR6:
+ return "SRC_GPR6";
+ case SRC_GPR7:
+ return "SRC_GPR7";
+ case SRC_GPR8:
+ return "SRC_GPR8";
+ case SRC_GPR9:
+ return "SRC_GPR9";
+ case SRC_GPR10:
+ return "SRC_GPR10";
+ default:
+ sprintf(unknown, "%u ?", reg);
+ return unknown;
+ }
+}
+
+static const VMStateDescription vmstate_imx7_src = {
+ .name = TYPE_IMX7_SRC,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, IMX7SRCState, SRC_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx7_src_reset(DeviceState *dev)
+{
+ IMX7SRCState *s = IMX7_SRC(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ /* Set reset values */
+ s->regs[SRC_SCR] = 0xA0;
+ s->regs[SRC_SRSR] = 0x1;
+ s->regs[SRC_SIMR] = 0x1F;
+}
+
+static uint64_t imx7_src_read(void *opaque, hwaddr offset, unsigned size)
+{
+ uint32_t value = 0;
+ IMX7SRCState *s = (IMX7SRCState *)opaque;
+ uint32_t index = offset >> 2;
+
+ if (index < SRC_MAX) {
+ value = s->regs[index];
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset);
+ }
+
+ trace_imx7_src_read(imx7_src_reg_name(index), value);
+
+ return value;
+}
+
+
+/*
+ * The reset is asynchronous so we need to defer clearing the reset
+ * bit until the work is completed.
+ */
+
+struct SRCSCRResetInfo {
+ IMX7SRCState *s;
+ uint32_t reset_bit;
+};
+
+static void imx7_clear_reset_bit(CPUState *cpu, run_on_cpu_data data)
+{
+ struct SRCSCRResetInfo *ri = data.host_ptr;
+ IMX7SRCState *s = ri->s;
+
+ assert(qemu_mutex_iothread_locked());
+
+ s->regs[SRC_A7RCR0] = deposit32(s->regs[SRC_A7RCR0], ri->reset_bit, 1, 0);
+
+ trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]);
+
+ g_free(ri);
+}
+
+static void imx7_defer_clear_reset_bit(uint32_t cpuid,
+ IMX7SRCState *s,
+ uint32_t reset_shift)
+{
+ struct SRCSCRResetInfo *ri;
+ CPUState *cpu = arm_get_cpu_by_id(cpuid);
+
+ if (!cpu) {
+ return;
+ }
+
+ ri = g_new(struct SRCSCRResetInfo, 1);
+ ri->s = s;
+ ri->reset_bit = reset_shift;
+
+ async_run_on_cpu(cpu, imx7_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri));
+}
+
+
+static void imx7_src_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ IMX7SRCState *s = (IMX7SRCState *)opaque;
+ uint32_t index = offset >> 2;
+ long unsigned int change_mask;
+ uint32_t current_value = value;
+
+ if (index >= SRC_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset);
+ return;
+ }
+
+ trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]);
+
+ change_mask = s->regs[index] ^ (uint32_t)current_value;
+
+ switch (index) {
+ case SRC_A7RCR0:
+ if (FIELD_EX32(change_mask, CORE0, RST)) {
+ arm_reset_cpu(0);
+ imx7_defer_clear_reset_bit(0, s, R_CORE0_RST_SHIFT);
+ }
+ if (FIELD_EX32(change_mask, CORE1, RST)) {
+ arm_reset_cpu(1);
+ imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT);
+ }
+ s->regs[index] = current_value;
+ break;
+ case SRC_A7RCR1:
+ /*
+ * On real hardware when the system reset controller starts a
+ * secondary CPU it runs through some boot ROM code which reads
+ * the SRC_GPRX registers controlling the start address and branches
+ * to it.
+ * Here we are taking a short cut and branching directly to the
+ * requested address (we don't want to run the boot ROM code inside
+ * QEMU)
+ */
+ if (FIELD_EX32(change_mask, CORE1, ENABLE)) {
+ if (FIELD_EX32(current_value, CORE1, ENABLE)) {
+ /* CORE 1 is brought up */
+ arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4],
+ 3, false);
+ } else {
+ /* CORE 1 is shut down */
+ arm_set_cpu_off(1);
+ }
+ /* We clear the reset bits as the processor changed state */
+ imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT);
+ clear_bit(R_CORE1_RST_SHIFT, &change_mask);
+ }
+ s->regs[index] = current_value;
+ break;
+ default:
+ s->regs[index] = current_value;
+ break;
+ }
+}
+
+static const struct MemoryRegionOps imx7_src_ops = {
+ .read = imx7_src_read,
+ .write = imx7_src_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx7_src_realize(DeviceState *dev, Error **errp)
+{
+ IMX7SRCState *s = IMX7_SRC(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx7_src_ops, s,
+ TYPE_IMX7_SRC, 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+}
+
+static void imx7_src_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = imx7_src_realize;
+ dc->reset = imx7_src_reset;
+ dc->vmsd = &vmstate_imx7_src;
+ dc->desc = "i.MX6 System Reset Controller";
+}
+
+static const TypeInfo imx7_src_info = {
+ .name = TYPE_IMX7_SRC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX7SRCState),
+ .class_init = imx7_src_class_init,
+};
+
+static void imx7_src_register_types(void)
+{
+ type_register_static(&imx7_src_info);
+}
+
+type_init(imx7_src_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..d9a370c1de 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -60,6 +60,7 @@ system_ss.add(when: 'CONFIG_IMX', if_true: files(
'imx6_src.c',
'imx6ul_ccm.c',
'imx7_ccm.c',
+ 'imx7_src.c',
'imx7_gpr.c',
'imx7_snvs.c',
'imx_ccm.c',
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 4d1a0e17af..e8b2be14c0 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -199,6 +199,10 @@ ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d"
ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32
ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32
+# imx7_src.c
+imx7_src_read(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32
+imx7_src_write(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32
+
# iotkit-sysinfo.c
iotkit_sysinfo_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
diff --git a/hw/rtc/aspeed_rtc.c b/hw/rtc/aspeed_rtc.c
index f6da7b666d..fa861e2d49 100644
--- a/hw/rtc/aspeed_rtc.c
+++ b/hw/rtc/aspeed_rtc.c
@@ -136,11 +136,10 @@ static const MemoryRegionOps aspeed_rtc_ops = {
static const VMStateDescription vmstate_aspeed_rtc = {
.name = TYPE_ASPEED_RTC,
- .version_id = 1,
+ .version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(reg, AspeedRtcState, 0x18),
- VMSTATE_INT32(offset, AspeedRtcState),
- VMSTATE_INT32(offset, AspeedRtcState),
+ VMSTATE_INT64(offset, AspeedRtcState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c
index ec3e56e84f..2e2c849985 100644
--- a/hw/rtc/m48t59.c
+++ b/hw/rtc/m48t59.c
@@ -133,7 +133,7 @@ static void alarm_cb (void *opaque)
static void set_alarm(M48t59State *NVRAM)
{
- int diff;
+ int64_t diff;
if (NVRAM->alrm_timer != NULL) {
timer_del(NVRAM->alrm_timer);
diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c
index d8534dad94..64c61c3dae 100644
--- a/hw/rtc/twl92230.c
+++ b/hw/rtc/twl92230.c
@@ -65,8 +65,8 @@ struct MenelausState {
struct tm tm;
struct tm new;
struct tm alm;
- int sec_offset;
- int alm_sec;
+ int64_t sec_offset;
+ int64_t alm_sec;
int next_comp;
} rtc;
uint16_t rtc_next_vmstate;
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index cd0931d0a0..88b3b759c5 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -56,6 +56,9 @@
* (matching the hardware) is that for CPU0 in an IoTKit and CPU1 in an
* SSE-200 both are present; CPU0 in an SSE-200 has neither.
* Since the IoTKit has only one CPU, it does not have the CPU1_* properties.
+ * + QOM properties "CPU0_MPU_NS", "CPU0_MPU_S", "CPU1_MPU_NS" and "CPU1_MPU_S"
+ * which set the number of MPU regions on the CPUs. If there is only one
+ * CPU the CPU1 properties are not present.
* + 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
@@ -221,6 +224,8 @@ struct ARMSSE {
uint32_t exp_numirq;
uint32_t sram_addr_width;
uint32_t init_svtor;
+ uint32_t cpu_mpu_ns[SSE_MAX_CPUS];
+ uint32_t cpu_mpu_s[SSE_MAX_CPUS];
bool cpu_fpu[SSE_MAX_CPUS];
bool cpu_dsp[SSE_MAX_CPUS];
};
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
index b7ba0ff409..e2cebbd15c 100644
--- a/include/hw/arm/armv7m.h
+++ b/include/hw/arm/armv7m.h
@@ -52,6 +52,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
* + Property "vfp": enable VFP (forwarded to CPU object)
* + Property "dsp": enable DSP (forwarded to CPU object)
* + Property "enable-bitband": expose bitbanded IO
+ * + Property "mpu-ns-regions": number of Non-Secure MPU regions (forwarded
+ * to CPU object pmsav7-dregion property; default is whatever the default
+ * for the CPU is)
+ * + Property "mpu-s-regions": number of Secure MPU regions (default is
+ * whatever the default for the CPU is; must currently be set to the same
+ * value as mpu-ns-regions if the CPU implements the Security Extension)
* + Clock input "refclk" is the external reference clock for the systick timers
* + Clock input "cpuclk" is the main CPU clock
*/
@@ -95,6 +101,8 @@ struct ARMv7MState {
Object *idau;
uint32_t init_svtor;
uint32_t init_nsvtor;
+ uint32_t mpu_ns_regions;
+ uint32_t mpu_s_regions;
bool enable_bitband;
bool start_powered_off;
bool vfp;
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 9ee15ae38d..63012628ff 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -22,7 +22,6 @@
#include "hw/misc/imx6ul_ccm.h"
#include "hw/misc/imx6_src.h"
#include "hw/misc/imx7_snvs.h"
-#include "hw/misc/imx7_gpr.h"
#include "hw/intc/imx_gpcv2.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
@@ -38,6 +37,7 @@
#include "exec/memory.h"
#include "cpu.h"
#include "qom/object.h"
+#include "qemu/units.h"
#define TYPE_FSL_IMX6UL "fsl-imx6ul"
OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL)
@@ -58,6 +58,9 @@ enum FslIMX6ULConfiguration {
FSL_IMX6UL_NUM_ADCS = 2,
FSL_IMX6UL_NUM_USB_PHYS = 2,
FSL_IMX6UL_NUM_USBS = 2,
+ FSL_IMX6UL_NUM_SAIS = 3,
+ FSL_IMX6UL_NUM_CANS = 2,
+ FSL_IMX6UL_NUM_PWMS = 8,
};
struct FslIMX6ULState {
@@ -74,7 +77,6 @@ struct FslIMX6ULState {
IMX6SRCState src;
IMX7SNVSState snvs;
IMXGPCv2State gpcv2;
- IMX7GPRState gpr;
IMXSPIState spi[FSL_IMX6UL_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX6UL_NUM_I2CS];
IMXSerialState uart[FSL_IMX6UL_NUM_UARTS];
@@ -94,119 +96,227 @@ struct FslIMX6ULState {
enum FslIMX6ULMemoryMap {
FSL_IMX6UL_MMDC_ADDR = 0x80000000,
- FSL_IMX6UL_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+ FSL_IMX6UL_MMDC_SIZE = (2 * GiB),
FSL_IMX6UL_QSPI1_MEM_ADDR = 0x60000000,
+ FSL_IMX6UL_QSPI1_MEM_SIZE = (256 * MiB),
+
FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
+ FSL_IMX6UL_EIM_ALIAS_SIZE = (128 * MiB),
+
FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
+ FSL_IMX6UL_EIM_CS_SIZE = (128 * MiB),
+
FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
+ FSL_IMX6UL_AES_ENCRYPT_SIZE = (1 * MiB),
+
FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
+ FSL_IMX6UL_QSPI1_RX_SIZE = (32 * MiB),
- /* AIPS-2 */
+ /* AIPS-2 Begin */
FSL_IMX6UL_UART6_ADDR = 0x021FC000,
+
FSL_IMX6UL_I2C4_ADDR = 0x021F8000,
+
FSL_IMX6UL_UART5_ADDR = 0x021F4000,
FSL_IMX6UL_UART4_ADDR = 0x021F0000,
FSL_IMX6UL_UART3_ADDR = 0x021EC000,
FSL_IMX6UL_UART2_ADDR = 0x021E8000,
+
FSL_IMX6UL_WDOG3_ADDR = 0x021E4000,
+
FSL_IMX6UL_QSPI_ADDR = 0x021E0000,
+ FSL_IMX6UL_QSPI_SIZE = 0x500,
+
FSL_IMX6UL_SYS_CNT_CTRL_ADDR = 0x021DC000,
+ FSL_IMX6UL_SYS_CNT_CTRL_SIZE = (16 * KiB),
+
FSL_IMX6UL_SYS_CNT_CMP_ADDR = 0x021D8000,
+ FSL_IMX6UL_SYS_CNT_CMP_SIZE = (16 * KiB),
+
FSL_IMX6UL_SYS_CNT_RD_ADDR = 0x021D4000,
+ FSL_IMX6UL_SYS_CNT_RD_SIZE = (16 * KiB),
+
FSL_IMX6UL_TZASC_ADDR = 0x021D0000,
+ FSL_IMX6UL_TZASC_SIZE = (16 * KiB),
+
FSL_IMX6UL_PXP_ADDR = 0x021CC000,
+ FSL_IMX6UL_PXP_SIZE = (16 * KiB),
+
FSL_IMX6UL_LCDIF_ADDR = 0x021C8000,
+ FSL_IMX6UL_LCDIF_SIZE = 0x100,
+
FSL_IMX6UL_CSI_ADDR = 0x021C4000,
+ FSL_IMX6UL_CSI_SIZE = 0x100,
+
FSL_IMX6UL_CSU_ADDR = 0x021C0000,
+ FSL_IMX6UL_CSU_SIZE = (16 * KiB),
+
FSL_IMX6UL_OCOTP_CTRL_ADDR = 0x021BC000,
+ FSL_IMX6UL_OCOTP_CTRL_SIZE = (4 * KiB),
+
FSL_IMX6UL_EIM_ADDR = 0x021B8000,
+ FSL_IMX6UL_EIM_SIZE = 0x100,
+
FSL_IMX6UL_SIM2_ADDR = 0x021B4000,
+
FSL_IMX6UL_MMDC_CFG_ADDR = 0x021B0000,
+ FSL_IMX6UL_MMDC_CFG_SIZE = (4 * KiB),
+
FSL_IMX6UL_ROMCP_ADDR = 0x021AC000,
+ FSL_IMX6UL_ROMCP_SIZE = 0x300,
+
FSL_IMX6UL_I2C3_ADDR = 0x021A8000,
FSL_IMX6UL_I2C2_ADDR = 0x021A4000,
FSL_IMX6UL_I2C1_ADDR = 0x021A0000,
+
FSL_IMX6UL_ADC2_ADDR = 0x0219C000,
FSL_IMX6UL_ADC1_ADDR = 0x02198000,
+ FSL_IMX6UL_ADCn_SIZE = 0x100,
+
FSL_IMX6UL_USDHC2_ADDR = 0x02194000,
FSL_IMX6UL_USDHC1_ADDR = 0x02190000,
+
FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
+ FSL_IMX6UL_SIMn_SIZE = (16 * KiB),
+
FSL_IMX6UL_ENET1_ADDR = 0x02188000,
+
FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
- FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
+ FSL_IMX6UL_USBO2_USB1_ADDR = 0x02184000,
+ FSL_IMX6UL_USBO2_USB2_ADDR = 0x02184200,
+
FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
+ FSL_IMX6UL_USBO2_PL301_SIZE = (16 * KiB),
+
FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
+ FSL_IMX6UL_AIPS2_CFG_SIZE = 0x100,
+
FSL_IMX6UL_CAAM_ADDR = 0x02140000,
+ FSL_IMX6UL_CAAM_SIZE = (16 * KiB),
+
FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
+ FSL_IMX6UL_A7MPCORE_DAP_SIZE = (4 * KiB),
+ /* AIPS-2 End */
- /* AIPS-1 */
+ /* AIPS-1 Begin */
FSL_IMX6UL_PWM8_ADDR = 0x020FC000,
FSL_IMX6UL_PWM7_ADDR = 0x020F8000,
FSL_IMX6UL_PWM6_ADDR = 0x020F4000,
FSL_IMX6UL_PWM5_ADDR = 0x020F0000,
+
FSL_IMX6UL_SDMA_ADDR = 0x020EC000,
+ FSL_IMX6UL_SDMA_SIZE = 0x300,
+
FSL_IMX6UL_GPT2_ADDR = 0x020E8000,
+
FSL_IMX6UL_IOMUXC_GPR_ADDR = 0x020E4000,
+ FSL_IMX6UL_IOMUXC_GPR_SIZE = 0x40,
+
FSL_IMX6UL_IOMUXC_ADDR = 0x020E0000,
+ FSL_IMX6UL_IOMUXC_SIZE = 0x700,
+
FSL_IMX6UL_GPC_ADDR = 0x020DC000,
+
FSL_IMX6UL_SRC_ADDR = 0x020D8000,
+
FSL_IMX6UL_EPIT2_ADDR = 0x020D4000,
FSL_IMX6UL_EPIT1_ADDR = 0x020D0000,
+
FSL_IMX6UL_SNVS_HP_ADDR = 0x020CC000,
+
FSL_IMX6UL_USBPHY2_ADDR = 0x020CA000,
- FSL_IMX6UL_USBPHY2_SIZE = (4 * 1024),
FSL_IMX6UL_USBPHY1_ADDR = 0x020C9000,
- FSL_IMX6UL_USBPHY1_SIZE = (4 * 1024),
+
FSL_IMX6UL_ANALOG_ADDR = 0x020C8000,
+ FSL_IMX6UL_ANALOG_SIZE = 0x300,
+
FSL_IMX6UL_CCM_ADDR = 0x020C4000,
+
FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
FSL_IMX6UL_WDOG1_ADDR = 0x020BC000,
+
FSL_IMX6UL_KPP_ADDR = 0x020B8000,
+ FSL_IMX6UL_KPP_SIZE = 0x10,
+
FSL_IMX6UL_ENET2_ADDR = 0x020B4000,
+
FSL_IMX6UL_SNVS_LP_ADDR = 0x020B0000,
+ FSL_IMX6UL_SNVS_LP_SIZE = (16 * KiB),
+
FSL_IMX6UL_GPIO5_ADDR = 0x020AC000,
FSL_IMX6UL_GPIO4_ADDR = 0x020A8000,
FSL_IMX6UL_GPIO3_ADDR = 0x020A4000,
FSL_IMX6UL_GPIO2_ADDR = 0x020A0000,
FSL_IMX6UL_GPIO1_ADDR = 0x0209C000,
+
FSL_IMX6UL_GPT1_ADDR = 0x02098000,
+
FSL_IMX6UL_CAN2_ADDR = 0x02094000,
FSL_IMX6UL_CAN1_ADDR = 0x02090000,
+ FSL_IMX6UL_CANn_SIZE = (4 * KiB),
+
FSL_IMX6UL_PWM4_ADDR = 0x0208C000,
FSL_IMX6UL_PWM3_ADDR = 0x02088000,
FSL_IMX6UL_PWM2_ADDR = 0x02084000,
FSL_IMX6UL_PWM1_ADDR = 0x02080000,
+ FSL_IMX6UL_PWMn_SIZE = 0x20,
+
FSL_IMX6UL_AIPS1_CFG_ADDR = 0x0207C000,
+ FSL_IMX6UL_AIPS1_CFG_SIZE = (16 * KiB),
+
FSL_IMX6UL_BEE_ADDR = 0x02044000,
+ FSL_IMX6UL_BEE_SIZE = (16 * KiB),
+
FSL_IMX6UL_TOUCH_CTRL_ADDR = 0x02040000,
+ FSL_IMX6UL_TOUCH_CTRL_SIZE = 0x100,
+
FSL_IMX6UL_SPBA_ADDR = 0x0203C000,
+ FSL_IMX6UL_SPBA_SIZE = 0x100,
+
FSL_IMX6UL_ASRC_ADDR = 0x02034000,
+ FSL_IMX6UL_ASRC_SIZE = 0x100,
+
FSL_IMX6UL_SAI3_ADDR = 0x02030000,
FSL_IMX6UL_SAI2_ADDR = 0x0202C000,
FSL_IMX6UL_SAI1_ADDR = 0x02028000,
+ FSL_IMX6UL_SAIn_SIZE = 0x200,
+
FSL_IMX6UL_UART8_ADDR = 0x02024000,
FSL_IMX6UL_UART1_ADDR = 0x02020000,
FSL_IMX6UL_UART7_ADDR = 0x02018000,
+
FSL_IMX6UL_ECSPI4_ADDR = 0x02014000,
FSL_IMX6UL_ECSPI3_ADDR = 0x02010000,
FSL_IMX6UL_ECSPI2_ADDR = 0x0200C000,
FSL_IMX6UL_ECSPI1_ADDR = 0x02008000,
+
FSL_IMX6UL_SPDIF_ADDR = 0x02004000,
+ FSL_IMX6UL_SPDIF_SIZE = 0x100,
+ /* AIPS-1 End */
+
+ FSL_IMX6UL_BCH_ADDR = 0x01808000,
+ FSL_IMX6UL_BCH_SIZE = 0x200,
+
+ FSL_IMX6UL_GPMI_ADDR = 0x01806000,
+ FSL_IMX6UL_GPMI_SIZE = 0x200,
FSL_IMX6UL_APBH_DMA_ADDR = 0x01804000,
- FSL_IMX6UL_APBH_DMA_SIZE = (32 * 1024),
+ FSL_IMX6UL_APBH_DMA_SIZE = (4 * KiB),
FSL_IMX6UL_A7MPCORE_ADDR = 0x00A00000,
FSL_IMX6UL_OCRAM_ALIAS_ADDR = 0x00920000,
- FSL_IMX6UL_OCRAM_ALIAS_SIZE = 0x00060000,
+ FSL_IMX6UL_OCRAM_ALIAS_SIZE = (384 * KiB),
+
FSL_IMX6UL_OCRAM_MEM_ADDR = 0x00900000,
- FSL_IMX6UL_OCRAM_MEM_SIZE = 0x00020000,
+ FSL_IMX6UL_OCRAM_MEM_SIZE = (128 * KiB),
+
FSL_IMX6UL_CAAM_MEM_ADDR = 0x00100000,
- FSL_IMX6UL_CAAM_MEM_SIZE = 0x00008000,
+ FSL_IMX6UL_CAAM_MEM_SIZE = (32 * KiB),
+
FSL_IMX6UL_ROM_ADDR = 0x00000000,
- FSL_IMX6UL_ROM_SIZE = 0x00018000,
+ FSL_IMX6UL_ROM_SIZE = (96 * KiB),
};
enum FslIMX6ULIRQs {
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index fcce6421c8..2cbfc6b2b2 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -25,7 +25,7 @@
#include "hw/misc/imx7_ccm.h"
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
-#include "hw/misc/imx6_src.h"
+#include "hw/misc/imx7_src.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
@@ -39,6 +39,7 @@
#include "hw/usb/chipidea.h"
#include "cpu.h"
#include "qom/object.h"
+#include "qemu/units.h"
#define TYPE_FSL_IMX7 "fsl-imx7"
OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7)
@@ -57,6 +58,9 @@ enum FslIMX7Configuration {
FSL_IMX7_NUM_ECSPIS = 4,
FSL_IMX7_NUM_USBS = 3,
FSL_IMX7_NUM_ADCS = 2,
+ FSL_IMX7_NUM_SAIS = 3,
+ FSL_IMX7_NUM_CANS = 2,
+ FSL_IMX7_NUM_PWMS = 4,
};
struct FslIMX7State {
@@ -71,6 +75,7 @@ struct FslIMX7State {
IMX7CCMState ccm;
IMX7AnalogState analog;
IMX7SNVSState snvs;
+ IMX7SRCState src;
IMXGPCv2State gpcv2;
IMXSPIState spi[FSL_IMX7_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX7_NUM_I2CS];
@@ -81,86 +86,119 @@ struct FslIMX7State {
IMX7GPRState gpr;
ChipideaState usb[FSL_IMX7_NUM_USBS];
DesignwarePCIEHost pcie;
+ MemoryRegion rom;
+ MemoryRegion caam;
+ MemoryRegion ocram;
+ MemoryRegion ocram_epdc;
+ MemoryRegion ocram_pxp;
+ MemoryRegion ocram_s;
+
uint32_t phy_num[FSL_IMX7_NUM_ETHS];
bool phy_connected[FSL_IMX7_NUM_ETHS];
};
enum FslIMX7MemoryMap {
FSL_IMX7_MMDC_ADDR = 0x80000000,
- FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+ FSL_IMX7_MMDC_SIZE = (2 * GiB),
- FSL_IMX7_GPIO1_ADDR = 0x30200000,
- FSL_IMX7_GPIO2_ADDR = 0x30210000,
- FSL_IMX7_GPIO3_ADDR = 0x30220000,
- FSL_IMX7_GPIO4_ADDR = 0x30230000,
- FSL_IMX7_GPIO5_ADDR = 0x30240000,
- FSL_IMX7_GPIO6_ADDR = 0x30250000,
- FSL_IMX7_GPIO7_ADDR = 0x30260000,
+ FSL_IMX7_QSPI1_MEM_ADDR = 0x60000000,
+ FSL_IMX7_QSPI1_MEM_SIZE = (256 * MiB),
- FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
+ FSL_IMX7_PCIE1_MEM_ADDR = 0x40000000,
+ FSL_IMX7_PCIE1_MEM_SIZE = (256 * MiB),
- FSL_IMX7_WDOG1_ADDR = 0x30280000,
- FSL_IMX7_WDOG2_ADDR = 0x30290000,
- FSL_IMX7_WDOG3_ADDR = 0x302A0000,
- FSL_IMX7_WDOG4_ADDR = 0x302B0000,
+ FSL_IMX7_QSPI1_RX_BUF_ADDR = 0x34000000,
+ FSL_IMX7_QSPI1_RX_BUF_SIZE = (32 * MiB),
- FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
+ /* PCIe Peripherals */
+ FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
- FSL_IMX7_GPT1_ADDR = 0x302D0000,
- FSL_IMX7_GPT2_ADDR = 0x302E0000,
- FSL_IMX7_GPT3_ADDR = 0x302F0000,
- FSL_IMX7_GPT4_ADDR = 0x30300000,
+ /* MMAP Peripherals */
+ FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
+ FSL_IMX7_DMA_APBH_SIZE = 0x8000,
+
+ /* GPV configuration */
+ FSL_IMX7_GPV6_ADDR = 0x32600000,
+ FSL_IMX7_GPV5_ADDR = 0x32500000,
+ FSL_IMX7_GPV4_ADDR = 0x32400000,
+ FSL_IMX7_GPV3_ADDR = 0x32300000,
+ FSL_IMX7_GPV2_ADDR = 0x32200000,
+ FSL_IMX7_GPV1_ADDR = 0x32100000,
+ FSL_IMX7_GPV0_ADDR = 0x32000000,
+ FSL_IMX7_GPVn_SIZE = (1 * MiB),
+
+ /* Arm Peripherals */
+ FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
- FSL_IMX7_IOMUXC_ADDR = 0x30330000,
- FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
- FSL_IMX7_IOMUXCn_SIZE = 0x1000,
+ /* AIPS-3 Begin */
- FSL_IMX7_OCOTP_ADDR = 0x30350000,
- FSL_IMX7_OCOTP_SIZE = 0x10000,
+ FSL_IMX7_ENET2_ADDR = 0x30BF0000,
+ FSL_IMX7_ENET1_ADDR = 0x30BE0000,
- FSL_IMX7_ANALOG_ADDR = 0x30360000,
- FSL_IMX7_SNVS_ADDR = 0x30370000,
- FSL_IMX7_CCM_ADDR = 0x30380000,
+ FSL_IMX7_SDMA_ADDR = 0x30BD0000,
+ FSL_IMX7_SDMA_SIZE = (4 * KiB),
- FSL_IMX7_SRC_ADDR = 0x30390000,
- FSL_IMX7_SRC_SIZE = 0x1000,
+ FSL_IMX7_EIM_ADDR = 0x30BC0000,
+ FSL_IMX7_EIM_SIZE = (4 * KiB),
- FSL_IMX7_ADC1_ADDR = 0x30610000,
- FSL_IMX7_ADC2_ADDR = 0x30620000,
- FSL_IMX7_ADCn_SIZE = 0x1000,
+ FSL_IMX7_QSPI_ADDR = 0x30BB0000,
+ FSL_IMX7_QSPI_SIZE = 0x8000,
- FSL_IMX7_PWM1_ADDR = 0x30660000,
- FSL_IMX7_PWM2_ADDR = 0x30670000,
- FSL_IMX7_PWM3_ADDR = 0x30680000,
- FSL_IMX7_PWM4_ADDR = 0x30690000,
- FSL_IMX7_PWMn_SIZE = 0x10000,
+ FSL_IMX7_SIM2_ADDR = 0x30BA0000,
+ FSL_IMX7_SIM1_ADDR = 0x30B90000,
+ FSL_IMX7_SIMn_SIZE = (4 * KiB),
- FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
- FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
+ FSL_IMX7_USDHC3_ADDR = 0x30B60000,
+ FSL_IMX7_USDHC2_ADDR = 0x30B50000,
+ FSL_IMX7_USDHC1_ADDR = 0x30B40000,
- FSL_IMX7_GPC_ADDR = 0x303A0000,
+ FSL_IMX7_USB3_ADDR = 0x30B30000,
+ FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
+ FSL_IMX7_USB2_ADDR = 0x30B20000,
+ FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
+ FSL_IMX7_USB1_ADDR = 0x30B10000,
+ FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
+ FSL_IMX7_USBMISCn_SIZE = 0x200,
- FSL_IMX7_CAAM_ADDR = 0x30900000,
- FSL_IMX7_CAAM_SIZE = 0x40000,
+ FSL_IMX7_USB_PL301_ADDR = 0x30AD0000,
+ FSL_IMX7_USB_PL301_SIZE = (64 * KiB),
- FSL_IMX7_CAN1_ADDR = 0x30A00000,
- FSL_IMX7_CAN2_ADDR = 0x30A10000,
- FSL_IMX7_CANn_SIZE = 0x10000,
+ FSL_IMX7_SEMAPHORE_HS_ADDR = 0x30AC0000,
+ FSL_IMX7_SEMAPHORE_HS_SIZE = (64 * KiB),
+
+ FSL_IMX7_MUB_ADDR = 0x30AB0000,
+ FSL_IMX7_MUA_ADDR = 0x30AA0000,
+ FSL_IMX7_MUn_SIZE = (KiB),
+
+ FSL_IMX7_UART7_ADDR = 0x30A90000,
+ FSL_IMX7_UART6_ADDR = 0x30A80000,
+ FSL_IMX7_UART5_ADDR = 0x30A70000,
+ FSL_IMX7_UART4_ADDR = 0x30A60000,
- FSL_IMX7_I2C1_ADDR = 0x30A20000,
- FSL_IMX7_I2C2_ADDR = 0x30A30000,
- FSL_IMX7_I2C3_ADDR = 0x30A40000,
FSL_IMX7_I2C4_ADDR = 0x30A50000,
+ FSL_IMX7_I2C3_ADDR = 0x30A40000,
+ FSL_IMX7_I2C2_ADDR = 0x30A30000,
+ FSL_IMX7_I2C1_ADDR = 0x30A20000,
- FSL_IMX7_ECSPI1_ADDR = 0x30820000,
- FSL_IMX7_ECSPI2_ADDR = 0x30830000,
- FSL_IMX7_ECSPI3_ADDR = 0x30840000,
- FSL_IMX7_ECSPI4_ADDR = 0x30630000,
+ FSL_IMX7_CAN2_ADDR = 0x30A10000,
+ FSL_IMX7_CAN1_ADDR = 0x30A00000,
+ FSL_IMX7_CANn_SIZE = (4 * KiB),
- FSL_IMX7_LCDIF_ADDR = 0x30730000,
- FSL_IMX7_LCDIF_SIZE = 0x1000,
+ FSL_IMX7_AIPS3_CONF_ADDR = 0x309F0000,
+ FSL_IMX7_AIPS3_CONF_SIZE = (64 * KiB),
- FSL_IMX7_UART1_ADDR = 0x30860000,
+ FSL_IMX7_CAAM_ADDR = 0x30900000,
+ FSL_IMX7_CAAM_SIZE = (256 * KiB),
+
+ FSL_IMX7_SPBA_ADDR = 0x308F0000,
+ FSL_IMX7_SPBA_SIZE = (4 * KiB),
+
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
+ FSL_IMX7_SAI1_ADDR = 0x308A0000,
+ FSL_IMX7_SAIn_SIZE = (4 * KiB),
+
+ FSL_IMX7_UART3_ADDR = 0x30880000,
/*
* Some versions of the reference manual claim that UART2 is @
* 0x30870000, but experiments with HW + DT files in upstream
@@ -168,45 +206,173 @@ enum FslIMX7MemoryMap {
* actually located @ 0x30890000
*/
FSL_IMX7_UART2_ADDR = 0x30890000,
- FSL_IMX7_UART3_ADDR = 0x30880000,
- FSL_IMX7_UART4_ADDR = 0x30A60000,
- FSL_IMX7_UART5_ADDR = 0x30A70000,
- FSL_IMX7_UART6_ADDR = 0x30A80000,
- FSL_IMX7_UART7_ADDR = 0x30A90000,
+ FSL_IMX7_UART1_ADDR = 0x30860000,
- FSL_IMX7_SAI1_ADDR = 0x308A0000,
- FSL_IMX7_SAI2_ADDR = 0x308B0000,
- FSL_IMX7_SAI3_ADDR = 0x308C0000,
- FSL_IMX7_SAIn_SIZE = 0x10000,
+ FSL_IMX7_ECSPI3_ADDR = 0x30840000,
+ FSL_IMX7_ECSPI2_ADDR = 0x30830000,
+ FSL_IMX7_ECSPI1_ADDR = 0x30820000,
+ FSL_IMX7_ECSPIn_SIZE = (4 * KiB),
- FSL_IMX7_ENET1_ADDR = 0x30BE0000,
- FSL_IMX7_ENET2_ADDR = 0x30BF0000,
+ /* AIPS-3 End */
- FSL_IMX7_USB1_ADDR = 0x30B10000,
- FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
- FSL_IMX7_USB2_ADDR = 0x30B20000,
- FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
- FSL_IMX7_USB3_ADDR = 0x30B30000,
- FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
- FSL_IMX7_USBMISCn_SIZE = 0x200,
+ /* AIPS-2 Begin */
- FSL_IMX7_USDHC1_ADDR = 0x30B40000,
- FSL_IMX7_USDHC2_ADDR = 0x30B50000,
- FSL_IMX7_USDHC3_ADDR = 0x30B60000,
+ FSL_IMX7_AXI_DEBUG_MON_ADDR = 0x307E0000,
+ FSL_IMX7_AXI_DEBUG_MON_SIZE = (64 * KiB),
- FSL_IMX7_SDMA_ADDR = 0x30BD0000,
- FSL_IMX7_SDMA_SIZE = 0x1000,
+ FSL_IMX7_PERFMON2_ADDR = 0x307D0000,
+ FSL_IMX7_PERFMON1_ADDR = 0x307C0000,
+ FSL_IMX7_PERFMONn_SIZE = (64 * KiB),
+
+ FSL_IMX7_DDRC_ADDR = 0x307A0000,
+ FSL_IMX7_DDRC_SIZE = (4 * KiB),
+
+ FSL_IMX7_DDRC_PHY_ADDR = 0x30790000,
+ FSL_IMX7_DDRC_PHY_SIZE = (4 * KiB),
+
+ FSL_IMX7_TZASC_ADDR = 0x30780000,
+ FSL_IMX7_TZASC_SIZE = (64 * KiB),
+
+ FSL_IMX7_MIPI_DSI_ADDR = 0x30760000,
+ FSL_IMX7_MIPI_DSI_SIZE = (4 * KiB),
+
+ FSL_IMX7_MIPI_CSI_ADDR = 0x30750000,
+ FSL_IMX7_MIPI_CSI_SIZE = 0x4000,
+
+ FSL_IMX7_LCDIF_ADDR = 0x30730000,
+ FSL_IMX7_LCDIF_SIZE = 0x8000,
+
+ FSL_IMX7_CSI_ADDR = 0x30710000,
+ FSL_IMX7_CSI_SIZE = (4 * KiB),
+
+ FSL_IMX7_PXP_ADDR = 0x30700000,
+ FSL_IMX7_PXP_SIZE = 0x4000,
+
+ FSL_IMX7_EPDC_ADDR = 0x306F0000,
+ FSL_IMX7_EPDC_SIZE = (4 * KiB),
+
+ FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
+ FSL_IMX7_PCIE_PHY_SIZE = (4 * KiB),
+
+ FSL_IMX7_SYSCNT_CTRL_ADDR = 0x306C0000,
+ FSL_IMX7_SYSCNT_CMP_ADDR = 0x306B0000,
+ FSL_IMX7_SYSCNT_RD_ADDR = 0x306A0000,
+
+ FSL_IMX7_PWM4_ADDR = 0x30690000,
+ FSL_IMX7_PWM3_ADDR = 0x30680000,
+ FSL_IMX7_PWM2_ADDR = 0x30670000,
+ FSL_IMX7_PWM1_ADDR = 0x30660000,
+ FSL_IMX7_PWMn_SIZE = (4 * KiB),
+
+ FSL_IMX7_FlEXTIMER2_ADDR = 0x30650000,
+ FSL_IMX7_FlEXTIMER1_ADDR = 0x30640000,
+ FSL_IMX7_FLEXTIMERn_SIZE = (4 * KiB),
+
+ FSL_IMX7_ECSPI4_ADDR = 0x30630000,
+
+ FSL_IMX7_ADC2_ADDR = 0x30620000,
+ FSL_IMX7_ADC1_ADDR = 0x30610000,
+ FSL_IMX7_ADCn_SIZE = (4 * KiB),
+
+ FSL_IMX7_AIPS2_CONF_ADDR = 0x305F0000,
+ FSL_IMX7_AIPS2_CONF_SIZE = (64 * KiB),
+
+ /* AIPS-2 End */
+
+ /* AIPS-1 Begin */
+
+ FSL_IMX7_CSU_ADDR = 0x303E0000,
+ FSL_IMX7_CSU_SIZE = (64 * KiB),
+
+ FSL_IMX7_RDC_ADDR = 0x303D0000,
+ FSL_IMX7_RDC_SIZE = (4 * KiB),
+
+ FSL_IMX7_SEMAPHORE2_ADDR = 0x303C0000,
+ FSL_IMX7_SEMAPHORE1_ADDR = 0x303B0000,
+ FSL_IMX7_SEMAPHOREn_SIZE = (4 * KiB),
+
+ FSL_IMX7_GPC_ADDR = 0x303A0000,
+
+ FSL_IMX7_SRC_ADDR = 0x30390000,
+
+ FSL_IMX7_CCM_ADDR = 0x30380000,
+
+ FSL_IMX7_SNVS_HP_ADDR = 0x30370000,
+
+ FSL_IMX7_ANALOG_ADDR = 0x30360000,
+
+ FSL_IMX7_OCOTP_ADDR = 0x30350000,
+ FSL_IMX7_OCOTP_SIZE = 0x10000,
+
+ FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
+ FSL_IMX7_IOMUXC_GPR_SIZE = (4 * KiB),
+
+ FSL_IMX7_IOMUXC_ADDR = 0x30330000,
+ FSL_IMX7_IOMUXC_SIZE = (4 * KiB),
+
+ FSL_IMX7_KPP_ADDR = 0x30320000,
+ FSL_IMX7_KPP_SIZE = (4 * KiB),
+
+ FSL_IMX7_ROMCP_ADDR = 0x30310000,
+ FSL_IMX7_ROMCP_SIZE = (4 * KiB),
+
+ FSL_IMX7_GPT4_ADDR = 0x30300000,
+ FSL_IMX7_GPT3_ADDR = 0x302F0000,
+ FSL_IMX7_GPT2_ADDR = 0x302E0000,
+ FSL_IMX7_GPT1_ADDR = 0x302D0000,
+
+ FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
+ FSL_IMX7_IOMUXC_LPSR_SIZE = (4 * KiB),
+
+ FSL_IMX7_WDOG4_ADDR = 0x302B0000,
+ FSL_IMX7_WDOG3_ADDR = 0x302A0000,
+ FSL_IMX7_WDOG2_ADDR = 0x30290000,
+ FSL_IMX7_WDOG1_ADDR = 0x30280000,
+
+ FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
+
+ FSL_IMX7_GPIO7_ADDR = 0x30260000,
+ FSL_IMX7_GPIO6_ADDR = 0x30250000,
+ FSL_IMX7_GPIO5_ADDR = 0x30240000,
+ FSL_IMX7_GPIO4_ADDR = 0x30230000,
+ FSL_IMX7_GPIO3_ADDR = 0x30220000,
+ FSL_IMX7_GPIO2_ADDR = 0x30210000,
+ FSL_IMX7_GPIO1_ADDR = 0x30200000,
+
+ FSL_IMX7_AIPS1_CONF_ADDR = 0x301F0000,
+ FSL_IMX7_AIPS1_CONF_SIZE = (64 * KiB),
- FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000,
+ FSL_IMX7_A7MPCORE_DAP_SIZE = (1 * MiB),
- FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
- FSL_IMX7_PCIE_REG_SIZE = 16 * 1024,
+ /* AIPS-1 End */
- FSL_IMX7_GPR_ADDR = 0x30340000,
+ FSL_IMX7_EIM_CS0_ADDR = 0x28000000,
+ FSL_IMX7_EIM_CS0_SIZE = (128 * MiB),
- FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
- FSL_IMX7_DMA_APBH_SIZE = 0x2000,
+ FSL_IMX7_OCRAM_PXP_ADDR = 0x00940000,
+ FSL_IMX7_OCRAM_PXP_SIZE = (32 * KiB),
+
+ FSL_IMX7_OCRAM_EPDC_ADDR = 0x00920000,
+ FSL_IMX7_OCRAM_EPDC_SIZE = (128 * KiB),
+
+ FSL_IMX7_OCRAM_MEM_ADDR = 0x00900000,
+ FSL_IMX7_OCRAM_MEM_SIZE = (128 * KiB),
+
+ FSL_IMX7_TCMU_ADDR = 0x00800000,
+ FSL_IMX7_TCMU_SIZE = (32 * KiB),
+
+ FSL_IMX7_TCML_ADDR = 0x007F8000,
+ FSL_IMX7_TCML_SIZE = (32 * KiB),
+
+ FSL_IMX7_OCRAM_S_ADDR = 0x00180000,
+ FSL_IMX7_OCRAM_S_SIZE = (32 * KiB),
+
+ FSL_IMX7_CAAM_MEM_ADDR = 0x00100000,
+ FSL_IMX7_CAAM_MEM_SIZE = (32 * KiB),
+
+ FSL_IMX7_ROM_ADDR = 0x00000000,
+ FSL_IMX7_ROM_SIZE = (96 * KiB),
};
enum FslIMX7IRQs {
diff --git a/include/hw/misc/imx7_src.h b/include/hw/misc/imx7_src.h
new file mode 100644
index 0000000000..b4b97dcb1c
--- /dev/null
+++ b/include/hw/misc/imx7_src.h
@@ -0,0 +1,66 @@
+/*
+ * IMX7 System Reset Controller
+ *
+ * Copyright (C) 2023 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef IMX7_SRC_H
+#define IMX7_SRC_H
+
+#include "hw/sysbus.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+#define SRC_SCR 0
+#define SRC_A7RCR0 1
+#define SRC_A7RCR1 2
+#define SRC_M4RCR 3
+#define SRC_ERCR 5
+#define SRC_HSICPHY_RCR 7
+#define SRC_USBOPHY1_RCR 8
+#define SRC_USBOPHY2_RCR 9
+#define SRC_MPIPHY_RCR 10
+#define SRC_PCIEPHY_RCR 11
+#define SRC_SBMR1 22
+#define SRC_SRSR 23
+#define SRC_SISR 26
+#define SRC_SIMR 27
+#define SRC_SBMR2 28
+#define SRC_GPR1 29
+#define SRC_GPR2 30
+#define SRC_GPR3 31
+#define SRC_GPR4 32
+#define SRC_GPR5 33
+#define SRC_GPR6 34
+#define SRC_GPR7 35
+#define SRC_GPR8 36
+#define SRC_GPR9 37
+#define SRC_GPR10 38
+#define SRC_MAX 39
+
+/* SRC_A7SCR1 */
+#define R_CORE1_ENABLE_SHIFT 1
+#define R_CORE1_ENABLE_LENGTH 1
+/* SRC_A7SCR0 */
+#define R_CORE1_RST_SHIFT 5
+#define R_CORE1_RST_LENGTH 1
+#define R_CORE0_RST_SHIFT 4
+#define R_CORE0_RST_LENGTH 1
+
+#define TYPE_IMX7_SRC "imx7.src"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7SRCState, IMX7_SRC)
+
+struct IMX7SRCState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t regs[SRC_MAX];
+};
+
+#endif /* IMX7_SRC_H */
diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h
index df61e46059..596dfebb46 100644
--- a/include/hw/rtc/aspeed_rtc.h
+++ b/include/hw/rtc/aspeed_rtc.h
@@ -18,7 +18,7 @@ struct AspeedRtcState {
qemu_irq irq;
uint32_t reg[0x18];
- int offset;
+ int64_t offset;
};
diff --git a/include/sysemu/rtc.h b/include/sysemu/rtc.h
index 159702b45b..0fc8ad6fdf 100644
--- a/include/sysemu/rtc.h
+++ b/include/sysemu/rtc.h
@@ -42,7 +42,7 @@
* The behaviour of the clock whose value this function returns will
* depend on the -rtc command line option passed by the user.
*/
-void qemu_get_timedate(struct tm *tm, int offset);
+void qemu_get_timedate(struct tm *tm, time_t offset);
/**
* qemu_timedate_diff: Return difference between a struct tm and the RTC
@@ -53,6 +53,6 @@ void qemu_get_timedate(struct tm *tm, int offset);
* a timestamp one hour further ahead than the current RTC time
* then this function will return 3600.
*/
-int qemu_timedate_diff(struct tm *tm);
+time_t qemu_timedate_diff(struct tm *tm);
#endif
diff --git a/softmmu/rtc.c b/softmmu/rtc.c
index 4b2bf75dd6..4904581abe 100644
--- a/softmmu/rtc.c
+++ b/softmmu/rtc.c
@@ -68,7 +68,7 @@ static time_t qemu_ref_timedate(QEMUClockType clock)
return value;
}
-void qemu_get_timedate(struct tm *tm, int offset)
+void qemu_get_timedate(struct tm *tm, time_t offset)
{
time_t ti = qemu_ref_timedate(rtc_clock);
@@ -85,7 +85,7 @@ void qemu_get_timedate(struct tm *tm, int offset)
}
}
-int qemu_timedate_diff(struct tm *tm)
+time_t qemu_timedate_diff(struct tm *tm)
{
time_t seconds;
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 14785686f6..f1293d16c0 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -1077,4 +1077,6 @@ static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
#endif
+CPAccessResult access_tvm_trvm(CPUARMState *, const ARMCPRegInfo *, bool);
+
#endif /* TARGET_ARM_CPREGS_H */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d906d2b1ca..0bb0585441 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1356,17 +1356,108 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
}
+static void arm_cpu_propagate_feature_implications(ARMCPU *cpu)
+{
+ CPUARMState *env = &cpu->env;
+ bool no_aa32 = false;
+
+ /*
+ * Some features automatically imply others: set the feature
+ * bits explicitly for these cases.
+ */
+
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ set_feature(env, ARM_FEATURE_PMSA);
+ }
+
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ set_feature(env, ARM_FEATURE_V7);
+ } else {
+ set_feature(env, ARM_FEATURE_V7VE);
+ }
+ }
+
+ /*
+ * There exist AArch64 cpus without AArch32 support. When KVM
+ * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
+ * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
+ * As a general principle, we also do not make ID register
+ * consistency checks anywhere unless using TCG, because only
+ * for TCG would a consistency-check failure be a QEMU bug.
+ */
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
+ }
+
+ if (arm_feature(env, ARM_FEATURE_V7VE)) {
+ /*
+ * v7 Virtualization Extensions. In real hardware this implies
+ * EL2 and also the presence of the Security Extensions.
+ * For QEMU, for backwards-compatibility we implement some
+ * CPUs or CPU configs which have no actual EL2 or EL3 but do
+ * include the various other features that V7VE implies.
+ * Presence of EL2 itself is ARM_FEATURE_EL2, and of the
+ * Security Extensions is ARM_FEATURE_EL3.
+ */
+ assert(!tcg_enabled() || no_aa32 ||
+ cpu_isar_feature(aa32_arm_div, cpu));
+ set_feature(env, ARM_FEATURE_LPAE);
+ set_feature(env, ARM_FEATURE_V7);
+ }
+ if (arm_feature(env, ARM_FEATURE_V7)) {
+ set_feature(env, ARM_FEATURE_VAPA);
+ set_feature(env, ARM_FEATURE_THUMB2);
+ set_feature(env, ARM_FEATURE_MPIDR);
+ if (!arm_feature(env, ARM_FEATURE_M)) {
+ set_feature(env, ARM_FEATURE_V6K);
+ } else {
+ set_feature(env, ARM_FEATURE_V6);
+ }
+
+ /*
+ * Always define VBAR for V7 CPUs even if it doesn't exist in
+ * non-EL3 configs. This is needed by some legacy boards.
+ */
+ set_feature(env, ARM_FEATURE_VBAR);
+ }
+ if (arm_feature(env, ARM_FEATURE_V6K)) {
+ set_feature(env, ARM_FEATURE_V6);
+ set_feature(env, ARM_FEATURE_MVFR);
+ }
+ if (arm_feature(env, ARM_FEATURE_V6)) {
+ set_feature(env, ARM_FEATURE_V5);
+ if (!arm_feature(env, ARM_FEATURE_M)) {
+ assert(!tcg_enabled() || no_aa32 ||
+ cpu_isar_feature(aa32_jazelle, cpu));
+ set_feature(env, ARM_FEATURE_AUXCR);
+ }
+ }
+ if (arm_feature(env, ARM_FEATURE_V5)) {
+ set_feature(env, ARM_FEATURE_V4T);
+ }
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ set_feature(env, ARM_FEATURE_V7MP);
+ }
+ if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
+ set_feature(env, ARM_FEATURE_CBAR);
+ }
+ if (arm_feature(env, ARM_FEATURE_THUMB2) &&
+ !arm_feature(env, ARM_FEATURE_M)) {
+ set_feature(env, ARM_FEATURE_THUMB_DSP);
+ }
+}
+
void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
- /* M profile implies PMSA. We have to do this here rather than
- * in realize with the other feature-implication checks because
- * we look at the PMSA bit to see if we should add some properties.
+ /*
+ * Some features imply others. Figure this out now, because we
+ * are going to look at the feature bits in deciding which
+ * properties to add.
*/
- if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
- set_feature(&cpu->env, ARM_FEATURE_PMSA);
- }
+ arm_cpu_propagate_feature_implications(cpu);
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
@@ -1588,7 +1679,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
CPUARMState *env = &cpu->env;
int pagebits;
Error *local_err = NULL;
- bool no_aa32 = false;
/* Use pc-relative instructions in system-mode */
#ifndef CONFIG_USER_ONLY
@@ -1869,81 +1959,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
cpu->isar.id_isar3 = u;
}
- /* Some features automatically imply others: */
- if (arm_feature(env, ARM_FEATURE_V8)) {
- if (arm_feature(env, ARM_FEATURE_M)) {
- set_feature(env, ARM_FEATURE_V7);
- } else {
- set_feature(env, ARM_FEATURE_V7VE);
- }
- }
-
- /*
- * There exist AArch64 cpus without AArch32 support. When KVM
- * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
- * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
- * As a general principle, we also do not make ID register
- * consistency checks anywhere unless using TCG, because only
- * for TCG would a consistency-check failure be a QEMU bug.
- */
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
- no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
- }
-
- if (arm_feature(env, ARM_FEATURE_V7VE)) {
- /* v7 Virtualization Extensions. In real hardware this implies
- * EL2 and also the presence of the Security Extensions.
- * For QEMU, for backwards-compatibility we implement some
- * CPUs or CPU configs which have no actual EL2 or EL3 but do
- * include the various other features that V7VE implies.
- * Presence of EL2 itself is ARM_FEATURE_EL2, and of the
- * Security Extensions is ARM_FEATURE_EL3.
- */
- assert(!tcg_enabled() || no_aa32 ||
- cpu_isar_feature(aa32_arm_div, cpu));
- set_feature(env, ARM_FEATURE_LPAE);
- set_feature(env, ARM_FEATURE_V7);
- }
- if (arm_feature(env, ARM_FEATURE_V7)) {
- set_feature(env, ARM_FEATURE_VAPA);
- set_feature(env, ARM_FEATURE_THUMB2);
- set_feature(env, ARM_FEATURE_MPIDR);
- if (!arm_feature(env, ARM_FEATURE_M)) {
- set_feature(env, ARM_FEATURE_V6K);
- } else {
- set_feature(env, ARM_FEATURE_V6);
- }
-
- /* Always define VBAR for V7 CPUs even if it doesn't exist in
- * non-EL3 configs. This is needed by some legacy boards.
- */
- set_feature(env, ARM_FEATURE_VBAR);
- }
- if (arm_feature(env, ARM_FEATURE_V6K)) {
- set_feature(env, ARM_FEATURE_V6);
- set_feature(env, ARM_FEATURE_MVFR);
- }
- if (arm_feature(env, ARM_FEATURE_V6)) {
- set_feature(env, ARM_FEATURE_V5);
- if (!arm_feature(env, ARM_FEATURE_M)) {
- assert(!tcg_enabled() || no_aa32 ||
- cpu_isar_feature(aa32_jazelle, cpu));
- set_feature(env, ARM_FEATURE_AUXCR);
- }
- }
- if (arm_feature(env, ARM_FEATURE_V5)) {
- set_feature(env, ARM_FEATURE_V4T);
- }
- if (arm_feature(env, ARM_FEATURE_LPAE)) {
- set_feature(env, ARM_FEATURE_V7MP);
- }
- if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
- set_feature(env, ARM_FEATURE_CBAR);
- }
- if (arm_feature(env, ARM_FEATURE_THUMB2) &&
- !arm_feature(env, ARM_FEATURE_M)) {
- set_feature(env, ARM_FEATURE_THUMB_DSP);
- }
/*
* We rely on no XScale CPU having VFP so we can use the same bits in the
@@ -2056,16 +2071,27 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
ID_PFR1, VIRTUALIZATION, 0);
}
+ if (cpu_isar_feature(aa64_mte, cpu)) {
+ /*
+ * The architectural range of GM blocksize is 2-6, however qemu
+ * doesn't support blocksize of 2 (see HELPER(ldgm)).
+ */
+ if (tcg_enabled()) {
+ assert(cpu->gm_blocksize >= 3 && cpu->gm_blocksize <= 6);
+ }
+
#ifndef CONFIG_USER_ONLY
- if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
/*
- * Disable the MTE feature bits if we do not have tag-memory
- * provided by the machine.
+ * If we do not have tag-memory provided by the machine,
+ * reduce MTE support to instructions enabled at EL0.
+ * This matches Cortex-A710 BROADCASTMTE input being LOW.
*/
- cpu->isar.id_aa64pfr1 =
- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
- }
+ if (cpu->tag_memory == NULL) {
+ cpu->isar.id_aa64pfr1 =
+ FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1);
+ }
#endif
+ }
if (tcg_enabled()) {
/*
@@ -2077,6 +2103,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
/* FEAT_SPE (Statistical Profiling Extension) */
cpu->isar.id_aa64dfr0 =
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0);
+ /* FEAT_TRBE (Trace Buffer Extension) */
+ cpu->isar.id_aa64dfr0 =
+ FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0);
/* FEAT_TRF (Self-hosted Trace Extension) */
cpu->isar.id_aa64dfr0 =
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index cdf8600b96..278cc135c2 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1074,7 +1074,10 @@ struct ArchCPU {
bool prop_lpa2;
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
- uint32_t dcz_blocksize;
+ uint8_t dcz_blocksize;
+ /* GM blocksize, in log_2(words), ie low 4 bits of GMID_EL0 */
+ uint8_t gm_blocksize;
+
uint64_t rvbar_prop; /* Property/input signals. */
/* Configurable aspects of GIC cpu interface (which is part of the CPU) */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 85291d5b8e..e3f5a7d2bd 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -319,8 +319,8 @@ static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
}
/* Check for traps from EL1 due to HCR_EL2.TVM and HCR_EL2.TRVM. */
-static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
- bool isread)
+CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
{
if (arm_current_el(env) == 1) {
uint64_t trap = isread ? HCR_TRVM : HCR_TVM;
@@ -7748,10 +7748,6 @@ static const ARMCPRegInfo mte_reginfo[] = {
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
.access = PL1_RW, .accessfn = access_mte,
.fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) },
- { .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
- .access = PL1_R, .accessfn = access_aa64_tid5,
- .type = ARM_CP_CONST, .resetvalue = GMID_EL1_BS },
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
.type = ARM_CP_NO_RAW,
@@ -9342,6 +9338,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
* then define only a RAZ/WI version of PSTATE.TCO.
*/
if (cpu_isar_feature(aa64_mte, cpu)) {
+ ARMCPRegInfo gmid_reginfo = {
+ .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
+ .access = PL1_R, .accessfn = access_aa64_tid5,
+ .type = ARM_CP_CONST, .resetvalue = cpu->gm_blocksize,
+ };
+ define_one_arm_cp_reg(cpu, &gmid_reginfo);
define_arm_cp_regs(cpu, mte_reginfo);
define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
} else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) {
diff --git a/target/arm/internals.h b/target/arm/internals.h
index cf13bb94f5..5f5393b25c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1247,12 +1247,6 @@ void arm_log_exception(CPUState *cs);
#endif /* !CONFIG_USER_ONLY */
/*
- * The log2 of the words in the tag block, for GMID_EL1.BS.
- * The is the maximum, 256 bytes, which manipulates 64-bits of tags.
- */
-#define GMID_EL1_BS 6
-
-/*
* SVE predicates are 1/8 the size of SVE vectors, and cannot use
* the same simd_desc() encoding due to restrictions on size.
* Use these instead.
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 47d2e8e781..1f918ff537 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -62,7 +62,7 @@ void aa32_max_features(ARMCPU *cpu)
cpu->isar.id_mmfr3 = t;
t = cpu->isar.id_mmfr4;
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* FEAT_AA32HPD */
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 2); /* FEAT_HPDS2 */
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */
t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 8019f00bc3..0f8972950d 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -24,9 +24,36 @@
#include "qemu/module.h"
#include "qapi/visitor.h"
#include "hw/qdev-properties.h"
+#include "qemu/units.h"
#include "internals.h"
#include "cpregs.h"
+static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize,
+ unsigned cachesize)
+{
+ unsigned lg_linesize = ctz32(linesize);
+ unsigned sets;
+
+ /*
+ * The 64-bit CCSIDR_EL1 format is:
+ * [55:32] number of sets - 1
+ * [23:3] associativity - 1
+ * [2:0] log2(linesize) - 4
+ * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
+ */
+ assert(assoc != 0);
+ assert(is_power_of_2(linesize));
+ assert(lg_linesize >= 4 && lg_linesize <= 7 + 4);
+
+ /* sets * associativity * linesize == cachesize. */
+ sets = cachesize / (assoc * linesize);
+ assert(cachesize % (assoc * linesize) == 0);
+
+ return ((uint64_t)(sets - 1) << 32)
+ | ((assoc - 1) << 3)
+ | (lg_linesize - 4);
+}
+
static void aarch64_a35_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -436,10 +463,30 @@ static void aarch64_a64fx_initfn(Object *obj)
/* TODO: Add A64FX specific HPC extension registers */
}
+static CPAccessResult access_actlr_w(CPUARMState *env, const ARMCPRegInfo *r,
+ bool read)
+{
+ if (!read) {
+ int el = arm_current_el(env);
+
+ /* Because ACTLR_EL2 is constant 0, writes below EL2 trap to EL2. */
+ if (el < 2 && arm_is_el2_enabled(env)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ /* Because ACTLR_EL3 is constant 0, writes below EL3 trap to EL3. */
+ if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
{ .name = "ATCR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 7, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ /* Traps and enables are the same as for TCR_EL1. */
+ .accessfn = access_tvm_trvm, .fgt = FGT_TCR_EL1, },
{ .name = "ATCR_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 0,
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -454,13 +501,16 @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "CPUACTLR2_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 1,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "CPUACTLR3_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 2,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
/*
* Report CPUCFR_EL1.SCU as 1, as we do not implement the DSU
* (and in particular its system registers).
@@ -470,7 +520,8 @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 4 },
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 4,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0x961563010 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0x961563010,
+ .accessfn = access_actlr_w },
{ .name = "CPUPCR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 1,
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -485,16 +536,20 @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUPWRCTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "ERXPFGCDN_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 2,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "ERXPFGCTL_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 1,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "ERXPFGF_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
};
static void define_neoverse_n1_cp_reginfo(ARMCPU *cpu)
@@ -505,7 +560,8 @@ static void define_neoverse_n1_cp_reginfo(ARMCPU *cpu)
static const ARMCPRegInfo neoverse_v1_cp_reginfo[] = {
{ .name = "CPUECTLR2_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 5,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
{ .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 0,
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -651,26 +707,15 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
* The Neoverse-V1 r1p2 TRM lists 32-bit format CCSIDR_EL1 values,
* but also says it implements CCIDX, which means they should be
* 64-bit format. So we here use values which are based on the textual
- * information in chapter 2 of the TRM (and on the fact that
- * sets * associativity * linesize == cachesize).
- *
- * The 64-bit CCSIDR_EL1 format is:
- * [55:32] number of sets - 1
- * [23:3] associativity - 1
- * [2:0] log2(linesize) - 4
- * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
- *
- * L1: 4-way set associative 64-byte line size, total size 64K,
- * so sets is 256.
+ * information in chapter 2 of the TRM:
*
+ * L1: 4-way set associative 64-byte line size, total size 64K.
* L2: 8-way set associative, 64 byte line size, either 512K or 1MB.
- * We pick 1MB, so this has 2048 sets.
- *
* L3: No L3 (this matches the CLIDR_EL1 value).
*/
- cpu->ccsidr[0] = 0x000000ff0000001aull; /* 64KB L1 dcache */
- cpu->ccsidr[1] = 0x000000ff0000001aull; /* 64KB L1 icache */
- cpu->ccsidr[2] = 0x000007ff0000003aull; /* 1MB L2 cache */
+ cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */
+ cpu->ccsidr[1] = cpu->ccsidr[0]; /* L1 icache */
+ cpu->ccsidr[2] = make_ccsidr64(8, 64, 1 * MiB); /* L2 cache */
/* From 3.2.115 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -743,7 +788,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */
t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */
t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */
- t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1); /* FEAT_CRC32 */
t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* FEAT_LSE */
t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* FEAT_RDM */
t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* FEAT_SHA3 */
@@ -807,7 +852,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
- t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
+ t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 2); /* FEAT_HPDS2 */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
@@ -868,6 +913,7 @@ void aarch64_max_tcg_initfn(Object *obj)
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */
#endif
+ cpu->gm_blocksize = 6; /* 256 bytes */
cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
cpu->sme_vq.supported = SVE_VQ_POW2_MAP;
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index 1c9370f07b..0cf56f6dc4 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -780,6 +780,15 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
spsr &= ~PSTATE_SS;
}
+ /*
+ * FEAT_RME forbids return from EL3 with an invalid security state.
+ * We don't need an explicit check for FEAT_RME here because we enforce
+ * in scr_write() that you can't set the NSE bit without it.
+ */
+ if (cur_el == 3 && (env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
+ goto illegal_return;
+ }
+
new_el = el_from_spsr(spsr);
if (new_el == -1) {
goto illegal_return;
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index 9c64def081..b23d11563a 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -421,46 +421,82 @@ void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr)
}
}
-#define LDGM_STGM_SIZE (4 << GMID_EL1_BS)
-
uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
{
int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC();
+ int gm_bs = env_archcpu(env)->gm_blocksize;
+ int gm_bs_bytes = 4 << gm_bs;
void *tag_mem;
+ uint64_t ret;
+ int shift;
- ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE);
+ ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
/* Trap if accessing an invalid page. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD,
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
+ gm_bs_bytes, MMU_DATA_LOAD,
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
/* The tag is squashed to zero if the page does not support tags. */
if (!tag_mem) {
return 0;
}
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
/*
- * We are loading 64-bits worth of tags. The ordering of elements
- * within the word corresponds to a 64-bit little-endian operation.
+ * The ordering of elements within the word corresponds to
+ * a little-endian operation. Computation of shift comes from
+ *
+ * index = address<LOG2_TAG_GRANULE+3:LOG2_TAG_GRANULE>
+ * data<index*4+3:index*4> = tag
+ *
+ * Because of the alignment of ptr above, BS=6 has shift=0.
+ * All memory operations are aligned. Defer support for BS=2,
+ * requiring insertion or extraction of a nibble, until we
+ * support a cpu that requires it.
*/
- return ldq_le_p(tag_mem);
+ switch (gm_bs) {
+ case 3:
+ /* 32 bytes -> 2 tags -> 8 result bits */
+ ret = *(uint8_t *)tag_mem;
+ break;
+ case 4:
+ /* 64 bytes -> 4 tags -> 16 result bits */
+ ret = cpu_to_le16(*(uint16_t *)tag_mem);
+ break;
+ case 5:
+ /* 128 bytes -> 8 tags -> 32 result bits */
+ ret = cpu_to_le32(*(uint32_t *)tag_mem);
+ break;
+ case 6:
+ /* 256 bytes -> 16 tags -> 64 result bits */
+ return cpu_to_le64(*(uint64_t *)tag_mem);
+ default:
+ /*
+ * CPU configured with unsupported/invalid gm blocksize.
+ * This is detected early in arm_cpu_realizefn.
+ */
+ g_assert_not_reached();
+ }
+ shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4;
+ return ret << shift;
}
void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
{
int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC();
+ int gm_bs = env_archcpu(env)->gm_blocksize;
+ int gm_bs_bytes = 4 << gm_bs;
void *tag_mem;
+ int shift;
- ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE);
+ ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
/* Trap if accessing an invalid page. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
+ gm_bs_bytes, MMU_DATA_LOAD,
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
/*
* Tag store only happens if the page support tags,
@@ -470,12 +506,30 @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
return;
}
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
- /*
- * We are storing 64-bits worth of tags. The ordering of elements
- * within the word corresponds to a 64-bit little-endian operation.
- */
- stq_le_p(tag_mem, val);
+ /* See LDGM for comments on BS and on shift. */
+ shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4;
+ val >>= shift;
+ switch (gm_bs) {
+ case 3:
+ /* 32 bytes -> 2 tags -> 8 result bits */
+ *(uint8_t *)tag_mem = val;
+ break;
+ case 4:
+ /* 64 bytes -> 4 tags -> 16 result bits */
+ *(uint16_t *)tag_mem = cpu_to_le16(val);
+ break;
+ case 5:
+ /* 128 bytes -> 8 tags -> 32 result bits */
+ *(uint32_t *)tag_mem = cpu_to_le32(val);
+ break;
+ case 6:
+ /* 256 bytes -> 16 tags -> 64 result bits */
+ *(uint64_t *)tag_mem = cpu_to_le64(val);
+ break;
+ default:
+ /* cpu configured with unsupported gm blocksize. */
+ g_assert_not_reached();
+ }
}
void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index da686cc953..0b77c92437 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -3786,7 +3786,7 @@ static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
gen_helper_stgm(cpu_env, addr, tcg_rt);
} else {
MMUAccessType acc = MMU_DATA_STORE;
- int size = 4 << GMID_EL1_BS;
+ int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
@@ -3818,7 +3818,7 @@ static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
gen_helper_ldgm(tcg_rt, cpu_env, addr);
} else {
MMUAccessType acc = MMU_DATA_LOAD;
- int size = 4 << GMID_EL1_BS;
+ int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
@@ -13896,6 +13896,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->cp_regs = arm_cpu->cp_regs;
dc->features = env->features;
dc->dcz_blocksize = arm_cpu->dcz_blocksize;
+ dc->gm_blocksize = arm_cpu->gm_blocksize;
#ifdef CONFIG_USER_ONLY
/* In sve_probe_page, we assume TBI is enabled. */
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index d1cacff0b2..f748ba6f39 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -151,6 +151,8 @@ typedef struct DisasContext {
int8_t btype;
/* A copy of cpu->dcz_blocksize. */
uint8_t dcz_blocksize;
+ /* A copy of cpu->gm_blocksize. */
+ uint8_t gm_blocksize;
/* True if this page is guarded. */
bool guarded_page;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */