target-arm queue:

* Some of the preliminary patches for Cortex-A710 support
  * i.MX7 and i.MX6UL refactoring
  * Implement SRC device for i.MX7
  * Catch illegal-exception-return from EL3 with bad NSE/NS
  * Use 64-bit offsets for holding time_t differences in RTC devices
  * Model correct number of MPU regions for an505, an521, an524 boards
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmTwbukZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3ihBD/wK8Iz0KpTAwZBDAodnSZrh
 tQnJAvYFp8CxA4O8sZ9IeWsZh90gzsTCZi0NqUTTzvWCJfxkB7qTPdlJT5IzVxou
 oEUk2aogSJhRA3XRJzqArXsPlnZGSYDbtwKx4VtfCvOCCH08Y7nhnFaRj1oFnR4Q
 0PE/8YtGXTBxLHrO8U3tomg7zElzOUP8ZVZtb30BOyw1jtfSD03IZR8dzpA43u1E
 Hh418WvVekmwFoFNh8yUeHzbyXMZufzvbJPuDGJ8pPWwIpvSG6chOnKF8jZll+Ur
 DqOsDkGlQgcBR2QwYfSPClrEkX8yahJ95PBfM6giG+DQC7OiElqXqTiUGZcpgUVo
 uSUbzS4YPsxCnyVV6SBXV+f/8hdXBxOSHTgl7OAFa8X9OwWwspxHJ/v2o/2ibnUT
 hTTkFp/w1nQwVEN8xf1DOUpm/J2Wr8UeH4f776daSrfKAol2BKbHb8dOgGLQCwqb
 G+iDcE4bkzRqly6f+uVk8xSEZDd9P1NYoxKV+gNlV1dTspdHVpTC+rXMa8dRw5hI
 4KgaAslj++Xa229xkjORXCJ1cICRIebYg7+SjvTtGBYsFV7plsCcYb/R9yLmhVCf
 fKHKKaYe9sQJ82apOIkTc+nnW8BQQx6XUmU/A//iZ8JGLk6DpJcZ8f1m/2rVZTsl
 9+lsmpBf4w+uR4o+Womhfw==
 =MFh3
 -----END PGP SIGNATURE-----

Merge tag 'pull-target-arm-20230831' of https://git.linaro.org/people/pmaydell/qemu-arm into staging

target-arm queue:
 * Some of the preliminary patches for Cortex-A710 support
 * i.MX7 and i.MX6UL refactoring
 * Implement SRC device for i.MX7
 * Catch illegal-exception-return from EL3 with bad NSE/NS
 * Use 64-bit offsets for holding time_t differences in RTC devices
 * Model correct number of MPU regions for an505, an521, an524 boards

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmTwbukZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3ihBD/wK8Iz0KpTAwZBDAodnSZrh
# tQnJAvYFp8CxA4O8sZ9IeWsZh90gzsTCZi0NqUTTzvWCJfxkB7qTPdlJT5IzVxou
# oEUk2aogSJhRA3XRJzqArXsPlnZGSYDbtwKx4VtfCvOCCH08Y7nhnFaRj1oFnR4Q
# 0PE/8YtGXTBxLHrO8U3tomg7zElzOUP8ZVZtb30BOyw1jtfSD03IZR8dzpA43u1E
# Hh418WvVekmwFoFNh8yUeHzbyXMZufzvbJPuDGJ8pPWwIpvSG6chOnKF8jZll+Ur
# DqOsDkGlQgcBR2QwYfSPClrEkX8yahJ95PBfM6giG+DQC7OiElqXqTiUGZcpgUVo
# uSUbzS4YPsxCnyVV6SBXV+f/8hdXBxOSHTgl7OAFa8X9OwWwspxHJ/v2o/2ibnUT
# hTTkFp/w1nQwVEN8xf1DOUpm/J2Wr8UeH4f776daSrfKAol2BKbHb8dOgGLQCwqb
# G+iDcE4bkzRqly6f+uVk8xSEZDd9P1NYoxKV+gNlV1dTspdHVpTC+rXMa8dRw5hI
# 4KgaAslj++Xa229xkjORXCJ1cICRIebYg7+SjvTtGBYsFV7plsCcYb/R9yLmhVCf
# fKHKKaYe9sQJ82apOIkTc+nnW8BQQx6XUmU/A//iZ8JGLk6DpJcZ8f1m/2rVZTsl
# 9+lsmpBf4w+uR4o+Womhfw==
# =MFh3
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 31 Aug 2023 06:43:53 EDT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full]
# gpg:                 aka "Peter Maydell <peter@archaic.org.uk>" [unknown]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* tag 'pull-target-arm-20230831' of https://git.linaro.org/people/pmaydell/qemu-arm: (24 commits)
  hw/arm: Set number of MPU regions correctly for an505, an521, an524
  hw/arm/armv7m: Add mpu-ns-regions and mpu-s-regions properties
  target/arm: Do all "ARM_FEATURE_X implies Y" checks in post_init
  rtc: Use time_t for passing and returning time offsets
  hw/rtc/aspeed_rtc: Use 64-bit offset for holding time_t difference
  hw/rtc/twl92230: Use int64_t for sec_offset and alm_sec
  hw/rtc/m48t59: Use 64-bit arithmetic in set_alarm()
  target/arm: Catch illegal-exception-return from EL3 with bad NSE/NS
  Add i.MX7 SRC device implementation
  Add i.MX7 missing TZ devices and memory regions
  Refactor i.MX7 processor code
  Add i.MX6UL missing devices.
  Refactor i.MX6UL processor code
  Remove i.MX7 IOMUX GPR device from i.MX6UL
  target/arm: properly document FEAT_CRC32
  target/arm: Implement FEAT_HPDS2 as a no-op
  target/arm: Suppress FEAT_TRBE (Trace Buffer Extension)
  target/arm: Apply access checks to neoverse-v1 special registers
  target/arm: Apply access checks to neoverse-n1 special registers
  target/arm: Introduce make_ccsidr64
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-08-31 08:31:03 -04:00
commit c4e5f9a29f
31 changed files with 1393 additions and 372 deletions

View File

@ -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)

View File

@ -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,

View File

@ -334,6 +334,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(),
};

View File

@ -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,
@ -537,42 +553,66 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
FSL_IMX6UL_WDOGn_IRQ[i]));
}
/*
* 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

View File

@ -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[] = {

View File

@ -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;

276
hw/misc/imx7_src.c Normal file
View File

@ -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)

View File

@ -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',

View File

@ -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"

View File

@ -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()
}
};

View File

@ -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;

View File

@ -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;

View File

@ -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];
};

View File

@ -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;

View File

@ -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_EIM_ALIAS_ADDR = 0x58000000,
FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
FSL_IMX6UL_QSPI1_MEM_SIZE = (256 * MiB),
/* AIPS-2 */
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 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_ENET1_ADDR = 0x02188000,
FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
FSL_IMX6UL_CAAM_ADDR = 0x02140000,
FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
/* AIPS-1 */
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_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 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 {

View File

@ -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,
FSL_IMX7_IOMUXC_ADDR = 0x30330000,
FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
FSL_IMX7_IOMUXCn_SIZE = 0x1000,
/* 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),
FSL_IMX7_OCOTP_ADDR = 0x30350000,
FSL_IMX7_OCOTP_SIZE = 0x10000,
/* Arm Peripherals */
FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
FSL_IMX7_ANALOG_ADDR = 0x30360000,
FSL_IMX7_SNVS_ADDR = 0x30370000,
FSL_IMX7_CCM_ADDR = 0x30380000,
/* AIPS-3 Begin */
FSL_IMX7_SRC_ADDR = 0x30390000,
FSL_IMX7_SRC_SIZE = 0x1000,
FSL_IMX7_ENET2_ADDR = 0x30BF0000,
FSL_IMX7_ENET1_ADDR = 0x30BE0000,
FSL_IMX7_ADC1_ADDR = 0x30610000,
FSL_IMX7_ADC2_ADDR = 0x30620000,
FSL_IMX7_ADCn_SIZE = 0x1000,
FSL_IMX7_SDMA_ADDR = 0x30BD0000,
FSL_IMX7_SDMA_SIZE = (4 * KiB),
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_EIM_ADDR = 0x30BC0000,
FSL_IMX7_EIM_SIZE = (4 * KiB),
FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
FSL_IMX7_QSPI_ADDR = 0x30BB0000,
FSL_IMX7_QSPI_SIZE = 0x8000,
FSL_IMX7_GPC_ADDR = 0x303A0000,
FSL_IMX7_SIM2_ADDR = 0x30BA0000,
FSL_IMX7_SIM1_ADDR = 0x30B90000,
FSL_IMX7_SIMn_SIZE = (4 * KiB),
FSL_IMX7_USDHC3_ADDR = 0x30B60000,
FSL_IMX7_USDHC2_ADDR = 0x30B50000,
FSL_IMX7_USDHC1_ADDR = 0x30B40000,
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_USB_PL301_ADDR = 0x30AD0000,
FSL_IMX7_USB_PL301_SIZE = (64 * KiB),
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_I2C4_ADDR = 0x30A50000,
FSL_IMX7_I2C3_ADDR = 0x30A40000,
FSL_IMX7_I2C2_ADDR = 0x30A30000,
FSL_IMX7_I2C1_ADDR = 0x30A20000,
FSL_IMX7_CAN2_ADDR = 0x30A10000,
FSL_IMX7_CAN1_ADDR = 0x30A00000,
FSL_IMX7_CANn_SIZE = (4 * KiB),
FSL_IMX7_AIPS3_CONF_ADDR = 0x309F0000,
FSL_IMX7_AIPS3_CONF_SIZE = (64 * KiB),
FSL_IMX7_CAAM_ADDR = 0x30900000,
FSL_IMX7_CAAM_SIZE = 0x40000,
FSL_IMX7_CAAM_SIZE = (256 * KiB),
FSL_IMX7_CAN1_ADDR = 0x30A00000,
FSL_IMX7_CAN2_ADDR = 0x30A10000,
FSL_IMX7_CANn_SIZE = 0x10000,
FSL_IMX7_SPBA_ADDR = 0x308F0000,
FSL_IMX7_SPBA_SIZE = (4 * KiB),
FSL_IMX7_I2C1_ADDR = 0x30A20000,
FSL_IMX7_I2C2_ADDR = 0x30A30000,
FSL_IMX7_I2C3_ADDR = 0x30A40000,
FSL_IMX7_I2C4_ADDR = 0x30A50000,
FSL_IMX7_SAI3_ADDR = 0x308C0000,
FSL_IMX7_SAI2_ADDR = 0x308B0000,
FSL_IMX7_SAI1_ADDR = 0x308A0000,
FSL_IMX7_SAIn_SIZE = (4 * KiB),
FSL_IMX7_ECSPI1_ADDR = 0x30820000,
FSL_IMX7_ECSPI2_ADDR = 0x30830000,
FSL_IMX7_ECSPI3_ADDR = 0x30840000,
FSL_IMX7_ECSPI4_ADDR = 0x30630000,
FSL_IMX7_LCDIF_ADDR = 0x30730000,
FSL_IMX7_LCDIF_SIZE = 0x1000,
FSL_IMX7_UART1_ADDR = 0x30860000,
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 {

View File

@ -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 */

View File

@ -18,7 +18,7 @@ struct AspeedRtcState {
qemu_irq irq;
uint32_t reg[0x18];
int offset;
int64_t offset;
};

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}
#ifndef CONFIG_USER_ONLY
if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
if (cpu_isar_feature(aa64_mte, cpu)) {
/*
* Disable the MTE feature bits if we do not have tag-memory
* provided by the machine.
* The architectural range of GM blocksize is 2-6, however qemu
* doesn't support blocksize of 2 (see HELPER(ldgm)).
*/
cpu->isar.id_aa64pfr1 =
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
}
if (tcg_enabled()) {
assert(cpu->gm_blocksize >= 3 && cpu->gm_blocksize <= 6);
}
#ifndef CONFIG_USER_ONLY
/*
* 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.
*/
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);

View File

@ -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) */

View File

@ -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)) {

View File

@ -1246,12 +1246,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.

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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. */

View File

@ -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 */