hw/arm/armsse: Unify init-svtor and cpuwait handling

At the moment the handling of init-svtor and cpuwait initial
values is split between armsse.c and iotkit-sysctl.c:
the code in armsse.c sets the initial state of the CPU
object by setting the init-svtor and start-powered-off
properties, but the iotkit-sysctl.c code has its own
code setting the reset values of its registers (which are
then used when updating the CPU when the guest makes
runtime changes).

Clean this up by making the armsse.c code set properties on the
iotkit-sysctl object to define the initial values of the
registers, so they always match the initial CPU state,
and update the comments in armsse.c accordingly.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190219125808.25174-9-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2019-02-28 10:55:16 +00:00
parent 0f862986e0
commit aab7a3786f
3 changed files with 42 additions and 30 deletions

View file

@ -11,6 +11,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/bitops.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "trace.h" #include "trace.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
@ -29,6 +30,7 @@ struct ARMSSEInfo {
int sram_banks; int sram_banks;
int num_cpus; int num_cpus;
uint32_t sys_version; uint32_t sys_version;
uint32_t cpuwait_rst;
SysConfigFormat sys_config_format; SysConfigFormat sys_config_format;
bool has_mhus; bool has_mhus;
bool has_ppus; bool has_ppus;
@ -43,6 +45,7 @@ static const ARMSSEInfo armsse_variants[] = {
.sram_banks = 1, .sram_banks = 1,
.num_cpus = 1, .num_cpus = 1,
.sys_version = 0x41743, .sys_version = 0x41743,
.cpuwait_rst = 0,
.sys_config_format = IoTKitFormat, .sys_config_format = IoTKitFormat,
.has_mhus = false, .has_mhus = false,
.has_ppus = false, .has_ppus = false,
@ -55,6 +58,7 @@ static const ARMSSEInfo armsse_variants[] = {
.sram_banks = 4, .sram_banks = 4,
.num_cpus = 2, .num_cpus = 2,
.sys_version = 0x22041743, .sys_version = 0x22041743,
.cpuwait_rst = 2,
.sys_config_format = SSE200Format, .sys_config_format = SSE200Format,
.has_mhus = true, .has_mhus = true,
.has_ppus = true, .has_ppus = true,
@ -495,30 +499,33 @@ static void armsse_realize(DeviceState *dev, Error **errp)
qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32); qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
/* /*
* In real hardware the initial Secure VTOR is set from the INITSVTOR0 * In real hardware the initial Secure VTOR is set from the INITSVTOR*
* register in the IoT Kit System Control Register block, and the * registers in the IoT Kit System Control Register block. In QEMU
* initial value of that is in turn specifiable by the FPGA that * we set the initial value here, and also the reset value of the
* instantiates the IoT Kit. In QEMU we don't implement this wrinkle, * sysctl register, from this object's QOM init-svtor property.
* and simply set the CPU's init-svtor to the IoT Kit default value. * If the guest changes the INITSVTOR* registers at runtime then the
* In SSE-200 the situation is similar, except that the default value * code in iotkit-sysctl.c will update the CPU init-svtor property
* is a reset-time signal input. Typically a board using the SSE-200 * (which will then take effect on the next CPU warm-reset).
* will have a system control processor whose boot firmware initializes *
* the INITSVTOR* registers before powering up the CPUs in any case, * Note that typically a board using the SSE-200 will have a system
* so the hardware's default value doesn't matter. QEMU doesn't emulate * control processor whose boot firmware initializes the INITSVTOR*
* registers before powering up the CPUs. QEMU doesn't emulate
* the control processor, so instead we behave in the way that the * the control processor, so instead we behave in the way that the
* firmware does. The initial value is configurable by the board code * firmware does: the initial value should be set by the board code
* to match whatever its firmware does. * (using the init-svtor property on the ARMSSE object) to match
* whatever its firmware does.
*/ */
qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor); qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
/* /*
* Start all CPUs except CPU0 powered down. In real hardware it is * CPUs start powered down if the corresponding bit in the CPUWAIT
* a configurable property of the SSE-200 which CPUs start powered up * register is 1. In real hardware the CPUWAIT register reset value is
* (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all * a configurable property of the SSE-200 (via the CPUWAIT0_RST and
* the boards we care about start CPU0 and leave CPU1 powered off, * CPUWAIT1_RST parameters), but since all the boards we care about
* we hard-code that for now. We can add QOM properties for this * start CPU0 and leave CPU1 powered off, we hard-code that in
* info->cpuwait_rst for now. We can add QOM properties for this
* later if necessary. * later if necessary.
*/ */
if (i > 0) { if (extract32(info->cpuwait_rst, i, 1)) {
object_property_set_bool(cpuobj, true, "start-powered-off", &err); object_property_set_bool(cpuobj, true, "start-powered-off", &err);
if (err) { if (err) {
error_propagate(errp, err); error_propagate(errp, err);
@ -999,6 +1006,12 @@ static void armsse_realize(DeviceState *dev, Error **errp)
/* System control registers */ /* System control registers */
object_property_set_int(OBJECT(&s->sysctl), info->sys_version, object_property_set_int(OBJECT(&s->sysctl), info->sys_version,
"SYS_VERSION", &err); "SYS_VERSION", &err);
object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst,
"CPUWAIT_RST", &err);
object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
"INITSVTOR0_RST", &err);
object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
"INITSVTOR1_RST", &err);
object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err); object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
if (err) { if (err) {
error_propagate(errp, err); error_propagate(errp, err);

View file

@ -404,18 +404,9 @@ static void iotkit_sysctl_reset(DeviceState *dev)
s->reset_syndrome = 1; s->reset_syndrome = 1;
s->reset_mask = 0; s->reset_mask = 0;
s->gretreg = 0; s->gretreg = 0;
s->initsvtor0 = 0x10000000; s->initsvtor0 = s->initsvtor0_rst;
s->initsvtor1 = 0x10000000; s->initsvtor1 = s->initsvtor1_rst;
if (s->is_sse200) { s->cpuwait = s->cpuwait_rst;
/*
* CPU 0 starts on, CPU 1 starts off. In real hardware this is
* configurable by the SoC integrator as a verilog parameter.
*/
s->cpuwait = 2;
} else {
/* CPU 0 starts on */
s->cpuwait = 0;
}
s->wicctrl = 0; s->wicctrl = 0;
s->scsecctrl = 0; s->scsecctrl = 0;
s->fclk_div = 0; s->fclk_div = 0;
@ -500,6 +491,11 @@ static const VMStateDescription iotkit_sysctl_vmstate = {
static Property iotkit_sysctl_props[] = { static Property iotkit_sysctl_props[] = {
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0), DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
0x10000000),
DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
0x10000000),
DEFINE_PROP_END_OF_LIST() DEFINE_PROP_END_OF_LIST()
}; };

View file

@ -62,6 +62,9 @@ typedef struct IoTKitSysCtl {
/* Properties */ /* Properties */
uint32_t sys_version; uint32_t sys_version;
uint32_t cpuwait_rst;
uint32_t initsvtor0_rst;
uint32_t initsvtor1_rst;
bool is_sse200; bool is_sse200;
} IoTKitSysCtl; } IoTKitSysCtl;