Add SSE-310 case statements for reads and writes.
Add new SSE-310 PIDR and CLIDR values.
Add new SSE-310 PPUINTSTAT register as RAZ with LOG_UMIMP on reads and
RO on writes.
Reviewed-by: Owen Giles <owen.giles@hpe.com>
Reviewed-by: Robert Elliott <elliott@hpe.com>
Signed-off-by: Simon Xu <simonxhy0404@gmail.com>
---
v1 -> v2
Add PPUINTSTAT register
Make sure comments don't separate case statements
---
hw/misc/iotkit-sysctl.c | 89 ++++++++++++++++++++++++++++++---
include/hw/misc/iotkit-sysctl.h | 1 +
2 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index dff89c677f..bdf59b5f85 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -51,6 +51,7 @@ REG32(CPUWAIT, 0x118)
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
REG32(WICCTRL, 0x120)
REG32(EWCTRL, 0x124)
+REG32(PPUINTSTAT, 0x128)
REG32(PWRCTRL, 0x1fc)
FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
@@ -87,6 +88,12 @@ static const int sse200_sysctl_id[] = {
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+static const int sse310_sysctl_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x54, 0xb8, 0x4b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
/*
* Set the initial secure vector table offset address for the core.
* This will take effect when the CPU next resets.
@@ -118,6 +125,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->scsecctrl;
break;
default:
@@ -130,6 +138,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->fclk_div;
break;
default:
@@ -142,6 +151,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->sysclk_div;
break;
default:
@@ -154,6 +164,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->clock_force;
break;
default:
@@ -180,6 +191,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->initsvtor1;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -192,6 +204,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->cpuwait;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
/* In SSE300 this is reserved (for INITSVTOR2) */
goto bad_offset;
default:
@@ -208,6 +221,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->nmi_enable;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
/* In SSE300 this is reserved (for INITSVTOR3) */
goto bad_offset;
default:
@@ -221,7 +235,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->wicctrl;
break;
case ARMSSE_SSE300:
- /* In SSE300 this offset is CPUWAIT */
+ case ARMSSE_SSE310:
+ /* In SSE300 and SSE310 this offset is CPUWAIT */
r = s->cpuwait;
break;
default:
@@ -236,19 +251,36 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->ewctrl;
break;
case ARMSSE_SSE300:
- /* In SSE300 this offset is NMI_ENABLE */
+ case ARMSSE_SSE310:
+ /* In SSE300 and SSE310 this offset is NMI_ENABLE */
r = s->nmi_enable;
break;
default:
g_assert_not_reached();
}
break;
+ case A_PPUINTSTAT:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ goto bad_offset;
+ case ARMSSE_SSE310:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PPUINTSTAT unimplemented\n");
+ r = s->ppuintstat;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
case A_PWRCTRL:
switch (s->sse_version) {
case ARMSSE_IOTKIT:
case ARMSSE_SSE200:
goto bad_offset;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->pwrctrl;
break;
default:
@@ -261,6 +293,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->pdcm_pd_sys_sense;
break;
default:
@@ -273,7 +306,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
case ARMSSE_SSE200:
goto bad_offset;
case ARMSSE_SSE300:
- r = s->pdcm_pd_cpu0_sense;
+ case ARMSSE_SSE310:
+ r = s->pdcm_pd_cpu0_sense;
break;
default:
g_assert_not_reached();
@@ -287,6 +321,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->pdcm_pd_sram0_sense;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -300,6 +335,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->pdcm_pd_sram1_sense;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -313,6 +349,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->pdcm_pd_sram2_sense;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->pdcm_pd_vmr0_sense;
break;
default:
@@ -327,6 +364,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->pdcm_pd_sram3_sense;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
r = s->pdcm_pd_vmr1_sense;
break;
default:
@@ -342,6 +380,9 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
case ARMSSE_SSE300:
r = sse200_sysctl_id[(offset - A_PID4) / 4];
break;
+ case ARMSSE_SSE310:
+ r = sse310_sysctl_id[(offset - A_PID4) / 4];
+ break;
default:
g_assert_not_reached();
}
@@ -367,7 +408,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
{
- int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
+ int num_cpus = (s->sse_version == ARMSSE_SSE300 ||
+ s->sse_version == ARMSSE_SSE310) ? 1 : 2;
int i;
for (i = 0; i < num_cpus; i++) {
@@ -418,7 +460,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
case A_INITSVTOR0:
switch (s->sse_version) {
case ARMSSE_SSE300:
- /* SSE300 has a LOCK bit which prevents further writes when set */
+ case ARMSSE_SSE310:
+ /* SSE300 and SSE310 have a LOCK bit which prevents further writes */
if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit INITSVTOR0 write when register locked\n");
@@ -443,6 +486,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
cpuwait_write(s, value);
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
/* In SSE300 this is reserved (for INITSVTOR2) */
goto bad_offset;
default:
@@ -457,7 +501,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->wicctrl = value;
break;
case ARMSSE_SSE300:
- /* In SSE300 this offset is CPUWAIT */
+ case ARMSSE_SSE310:
+ /* In SSE300 and SSE310 this offset is CPUWAIT */
cpuwait_write(s, value);
break;
default:
@@ -485,6 +530,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
s->scsecctrl = value;
break;
@@ -498,6 +544,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
s->fclk_div = value;
break;
@@ -511,6 +558,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
s->sysclk_div = value;
break;
@@ -524,6 +572,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
s->clock_force = value;
break;
@@ -540,6 +589,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
set_init_vtor(1, s->initsvtor1);
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -554,7 +604,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->ewctrl = value;
break;
case ARMSSE_SSE300:
- /* In SSE300 this offset is NMI_ENABLE */
+ case ARMSSE_SSE310:
+ /* In SSE300 and SSE310 this offset is NMI_ENABLE */
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
s->nmi_enable = value;
break;
@@ -562,12 +613,25 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
g_assert_not_reached();
}
break;
+ case A_PPUINTSTAT:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ goto bad_offset;
+ case ARMSSE_SSE310:
+ goto ro_offset;
+ default:
+ g_assert_not_reached();
+ }
+ break;
case A_PWRCTRL:
switch (s->sse_version) {
case ARMSSE_IOTKIT:
case ARMSSE_SSE200:
goto bad_offset;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit PWRCTRL write when register locked\n");
@@ -585,6 +649,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
goto bad_offset;
case ARMSSE_SSE200:
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP,
"IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
s->pdcm_pd_sys_sense = value;
@@ -599,6 +664,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
case ARMSSE_SSE200:
goto bad_offset;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP,
"IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
s->pdcm_pd_cpu0_sense = value;
@@ -617,6 +683,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->pdcm_pd_sram0_sense = value;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -632,6 +699,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->pdcm_pd_sram1_sense = value;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
goto bad_offset;
default:
g_assert_not_reached();
@@ -647,6 +715,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->pdcm_pd_sram2_sense = value;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP,
"IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
s->pdcm_pd_vmr0_sense = value;
@@ -665,6 +734,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->pdcm_pd_sram3_sense = value;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
qemu_log_mask(LOG_UNIMP,
"IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
s->pdcm_pd_vmr1_sense = value;
@@ -683,6 +753,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->nmi_enable = value;
break;
case ARMSSE_SSE300:
+ case ARMSSE_SSE310:
/* In SSE300 this is reserved (for INITSVTOR3) */
goto bad_offset;
default:
@@ -734,6 +805,7 @@ static void iotkit_sysctl_reset(DeviceState *dev)
s->clock_force = 0;
s->nmi_enable = 0;
s->ewctrl = 0;
+ s->ppuintstat = 0;
s->pwrctrl = 0x3;
s->pdcm_pd_sys_sense = 0x7f;
s->pdcm_pd_sram0_sense = 0;
@@ -769,7 +841,8 @@ static bool sse300_needed(void *opaque)
{
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
- return s->sse_version == ARMSSE_SSE300;
+ return s->sse_version == ARMSSE_SSE300 ||
+ s->sse_version == ARMSSE_SSE310;
}
static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index ce72258a84..8e1cf0012d 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -53,6 +53,7 @@ struct IoTKitSysCtl {
uint32_t initsvtor1;
uint32_t nmi_enable;
uint32_t ewctrl;
+ uint32_t ppuintstat;
uint32_t pwrctrl;
uint32_t pdcm_pd_sys_sense;
uint32_t pdcm_pd_sram0_sense;
--
2.53.0
On Wed, 5 Aug 2026 at 16:30, Simon Xu <simonxhy0404@gmail.com> wrote:
>
> Add SSE-310 case statements for reads and writes.
> Add new SSE-310 PIDR and CLIDR values.
> Add new SSE-310 PPUINTSTAT register as RAZ with LOG_UMIMP on reads and
> RO on writes.
>
> Reviewed-by: Owen Giles <owen.giles@hpe.com>
> Reviewed-by: Robert Elliott <elliott@hpe.com>
> Signed-off-by: Simon Xu <simonxhy0404@gmail.com>
> ---
> v1 -> v2
> Add PPUINTSTAT register
> Make sure comments don't separate case statements
> static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
> diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
> index ce72258a84..8e1cf0012d 100644
> --- a/include/hw/misc/iotkit-sysctl.h
> +++ b/include/hw/misc/iotkit-sysctl.h
> @@ -53,6 +53,7 @@ struct IoTKitSysCtl {
> uint32_t initsvtor1;
> uint32_t nmi_enable;
> uint32_t ewctrl;
> + uint32_t ppuintstat;
> uint32_t pwrctrl;
> uint32_t pdcm_pd_sys_sense;
> uint32_t pdcm_pd_sram0_sense;
If we add a new field to the state struct here, we need to
add it to the vmstate data structures for migration. That
means a new subsection with an sse310_needed() function
so we migrate the field for SSE310 only.
But since this field is only ever zero because the register
is read-only, I think it's simpler to just have "r = 0;" in the
register-read codepath, and drop the field entirely. If anybody
ever needs to implement the register to have real functionality
they can add whatever fields/migration handling they need for it
then; we don't need to try to guess now what that will be.
thanks
-- PMM
© 2016 - 2026 Red Hat, Inc.