Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and further changes to support future SoCs beyond EarlGrey #37

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions docs/opentitan/pyot.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Virtual machine:
trace event definition file
-i N, --icount N virtual instruction counter with 2^N clock ticks per inst.
-s, --singlestep enable "single stepping" QEMU execution mode
-U, --muxserial enable multiple virtual UARTs to be muxed into same host output channel

Files:
-r ELF, --rom ELF ROM ELF file
Expand Down Expand Up @@ -102,6 +103,8 @@ This tool may be used in two ways, which can be combined:
matches the expected FPGA-based lowRISC CPU.
Note that this option slows down the execution of guest applications.
* `-s` / `--singlestep` enable QEMU "single stepping" mode.
* `-U` / `--muxserial` enable muxing QEMU VCP. This option is required when several virtual UARTs
are routed to the same host output channel.

### File options:

Expand Down Expand Up @@ -324,6 +327,23 @@ Sample config for running some non-OpenTitan tests:
{
timeout: 6
}
mbxhost-test:
{
env:
{
PYTHONPATH: ${QEMU_SRC_DIR}/scripts/opentitan
}
opts:
[
-chardev socket,id=devproxy,host=localhost,port=8003,server=on,wait=off
-global ot-dev_proxy.chardev=devproxy
]
with:
[
${BASEDIR}/tools/mbxhost_test.py -vv -I 3 -P 3 -t
]
timeout: 20
}
spihost-test:
{
# This test needs a specific SPI flash image
Expand Down Expand Up @@ -372,9 +392,11 @@ Sample config for running some non-OpenTitan tests:
Note that the resulting aliases are always uppercased.

To use an alias, use the `${ALIAS}` syntax. Environment variables may also be used as aliases.
Two special variables are automatically defined:
Several special variables are automatically defined:
* `${CONFIG}` refers to the path of the configuration file itself,
* `${TESTDIR}` refers to the default test path (see `testdir` below).
* `${QEMU_SRC_DIR}` refers to the path to the QEMU source directory
* `${QEMU_BIN_DIR}` refers to the directory than contains the QEMU executable.

* `testdir`
This section may be used to define the default path where to look for tests to run.
Expand Down Expand Up @@ -438,8 +460,7 @@ Sample config for running some non-OpenTitan tests:

### Special test sections

Each test section may have up to three special subsections that may be used to execute arbitrary
commands:
Each test section may have special subsections that may be used to execute arbitrary commands:

* `pre` subsection contains commands to execute before QEMU is executed.

Expand All @@ -455,6 +476,9 @@ commands:
* This section may be useful to perform some cleanup or post processing analysis once the QEMU
session is over

It is also possible to define an `env` section to define special environment variables that would be
required by the commands defined in the previous subsections.

Regular or 'synchronous' commands are only executed if all the previous commands have been
successful. Moreover, commands in the `post` subsection are only executed if the QEMU session has
completed successfully.
Expand Down
33 changes: 29 additions & 4 deletions docs/opentitan/rom_ctrl.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,38 @@ comparison happens).

## QEMU ROM Options

### Digest

The ROM digest is either a sequence of 64 hex digits (_i.e._ 32 bytes) or the exact string `fake` to
enable _fake digest_ mode).

### ELF ROM file

The ROM ELF file and its digest can be provided on the QEMU command line using this option:

```
-object ot-rom-img,id=rom,file=/path/to/rom.elf,digest=<romdigest>
```

The ROM image ID may depend on the SoC. For EarlGrey which has a single ROM, the ID is expected to
be `rom`.
### Binary ROM file

The ROM digest is either a sequence of 64 hex digits (_i.e._ 32 bytes) or the exact string `fake` to
enable _fake digest_ mode).
The ROM binary file and its digest can be provided on the QEMU command line using this option:

```
-object ot-rom-img,id=rom,file=/path/to/rom.bin,digest=<romdigest>,addr=address
```

If `addr` is specifed, the file is loaded as a raw binary file, whatever its extension.

`addr` is specified as an absolute address in the CPU address space, _i.e._ not relative to the
ROM base address.

### ROM identifiers

The ROM image ID may depend on the SoC.

* for EarlGrey which has a single ROM, the ID is expected to be `rom`.
* for a SoC with two ROMs, the IDs would be expected to be `rom0` and `rom1`.

## Booting with and without ROM

Expand All @@ -48,3 +69,7 @@ for the machine), it does not prevent the CPU from starting:
- ROM Controller activates _fake digest_ mode: digest is computed on the empty ROM region and
expected digest value is faked. ROM is "valid" so signal is sent to Power Manager to start the
CPU.

When the `-kernel` option is used, the default `resetvec` of the machine is overridden with the
entry point defined in the ELF file. The default `mtvec` is not modified - it is expected the ELF
early code updates the `mtvec` with a reachable location if no ROM is used.
6 changes: 5 additions & 1 deletion hw/opentitan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ config OT_ALERT_EARLGREY
config OT_AON_TIMER
bool

config OT_AST
config OT_AST_EARLGREY
bool

config OT_CLKMGR
Expand All @@ -30,6 +30,7 @@ config OT_EDN
bool

config OT_ENTROPY_SRC
select OT_RANDOM_SRC
bool

config OT_FLASH
Expand Down Expand Up @@ -74,6 +75,9 @@ config OT_PRNG
config OT_PWRMGR
bool

config OT_RANDOM_SRC
bool

config OT_ROM_CTRL
bool
select OT_COMMON
Expand Down
3 changes: 2 additions & 1 deletion hw/opentitan/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ softmmu_ss.add(when: 'CONFIG_OT_AES', if_true: [files('ot_aes.c'), libtomcrypt_d
softmmu_ss.add(when: 'CONFIG_OT_ALERT', if_true: files('ot_alert.c'))
softmmu_ss.add(when: 'CONFIG_OT_ALERT_EARLGREY', if_true: files('ot_alert_earlgrey.c'))
softmmu_ss.add(when: 'CONFIG_OT_AON_TIMER', if_true: files('ot_aon_timer.c'))
softmmu_ss.add(when: 'CONFIG_OT_AST', if_true: files('ot_ast.c'))
softmmu_ss.add(when: 'CONFIG_OT_AST_EARLGREY', if_true: files('ot_ast_earlgrey.c'))
softmmu_ss.add(when: 'CONFIG_OT_CLKMGR', if_true: files('ot_clkmgr.c'))
softmmu_ss.add(when: 'CONFIG_OT_COMMON', if_true: files('ot_common.c'))
softmmu_ss.add(when: 'CONFIG_OT_CSRNG', if_true: [files('ot_csrng.c'), libtomcrypt_dep])
Expand All @@ -27,6 +27,7 @@ softmmu_ss.add(when: 'CONFIG_OT_OTP_EARLGREY', if_true: files('ot_otp_earlgrey.c
softmmu_ss.add(when: 'CONFIG_OT_PINMUX', if_true: files('ot_pinmux.c'))
softmmu_ss.add(when: 'CONFIG_OT_PRNG', if_true: files('ot_prng.c'))
softmmu_ss.add(when: 'CONFIG_OT_PWRMGR', if_true: files('ot_pwrmgr.c'))
softmmu_ss.add(when: 'CONFIG_OT_RANDOM_SRC', if_true: files('ot_random_src.c'))
softmmu_ss.add(when: 'CONFIG_OT_ROM_CTRL', if_true: files('ot_rom_ctrl.c', 'ot_rom_ctrl_img.c'))
softmmu_ss.add(when: 'CONFIG_OT_RSTMGR', if_true: files('ot_rstmgr.c'))
softmmu_ss.add(when: 'CONFIG_OT_SENSOR', if_true: files('ot_sensor.c'))
Expand Down
18 changes: 11 additions & 7 deletions hw/opentitan/ot_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ typedef struct OtAESRegisters {
uint32_t status;

/* implementation */
DECLARE_BITMAP(keyshare_bm, PARAM_NUM_REGS_KEY * 2u);
DECLARE_BITMAP(keyshare_bm, (uint64_t)(PARAM_NUM_REGS_KEY * 2u));
DECLARE_BITMAP(iv_bm, PARAM_NUM_REGS_IV);
DECLARE_BITMAP(data_in_bm, PARAM_NUM_REGS_DATA);
DECLARE_BITMAP(data_out_bm, PARAM_NUM_REGS_DATA);
Expand Down Expand Up @@ -431,7 +431,7 @@ static void ot_aes_init_keyshare(OtAESState *s)

trace_ot_aes_init("keyshare");
ot_aes_randomize(s, r->keyshare, ARRAY_SIZE(r->keyshare));
bitmap_zero(r->keyshare_bm, PARAM_NUM_REGS_KEY * 2u);
bitmap_zero(r->keyshare_bm, (int64_t)(PARAM_NUM_REGS_KEY * 2u));
c->key_ready = false;
}

Expand Down Expand Up @@ -906,7 +906,8 @@ static void ot_aes_process_cond(OtAESState *s)
*/
timer_del(s->retard_timer);
uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
timer_mod(s->retard_timer, now + OT_AES_RETARD_DELAY_NS);
timer_mod(s->retard_timer,
(int64_t)(now + OT_AES_RETARD_DELAY_NS));
} else {
/*
* if fast mode is enabled, vCPU cannot resume execution before
Expand Down Expand Up @@ -973,6 +974,7 @@ static void ot_aes_reseed(OtAESState *s)
static uint64_t ot_aes_read(void *opaque, hwaddr addr, unsigned size)
{
OtAESState *s = opaque;
(void)size;
OtAESRegisters *r = s->regs;

uint32_t val32;
Expand Down Expand Up @@ -1018,7 +1020,7 @@ static uint64_t ot_aes_read(void *opaque, hwaddr addr, unsigned size)
case R_DATA_OUT_2:
case R_DATA_OUT_3:
val32 = r->data_out[reg - R_DATA_OUT_0];
clear_bit(reg - R_DATA_OUT_0, r->data_out_bm);
clear_bit((int64_t)(reg - R_DATA_OUT_0), r->data_out_bm);
if (bitmap_empty(r->data_out_bm, PARAM_NUM_REGS_DATA)) {
r->status &= ~R_STATUS_OUTPUT_VALID_MASK;
s->ctx->do_full = false;
Expand Down Expand Up @@ -1061,6 +1063,7 @@ static void ot_aes_write(void *opaque, hwaddr addr, uint64_t val64,
unsigned size)
{
OtAESState *s = opaque;
(void)size;
OtAESRegisters *r = s->regs;
uint32_t val32 = (uint32_t)val64;

Expand Down Expand Up @@ -1106,7 +1109,7 @@ static void ot_aes_write(void *opaque, hwaddr addr, uint64_t val64,
case R_KEY_SHARE1_7:
if (ot_aes_is_idle(s)) {
r->keyshare[reg - R_KEY_SHARE0_0] = val32;
set_bit(reg - R_KEY_SHARE0_0, r->keyshare_bm);
set_bit((int64_t)(reg - R_KEY_SHARE0_0), r->keyshare_bm);
ot_aes_update_key(s);
ot_aes_update_config(s);
}
Expand All @@ -1117,7 +1120,7 @@ static void ot_aes_write(void *opaque, hwaddr addr, uint64_t val64,
case R_IV_3:
if (ot_aes_is_idle(s)) {
r->iv[reg - R_IV_0] = val32;
set_bit(reg - R_IV_0, r->iv_bm);
set_bit((int64_t)(reg - R_IV_0), r->iv_bm);
ot_aes_update_iv(s);
ot_aes_update_config(s);
}
Expand All @@ -1127,7 +1130,7 @@ static void ot_aes_write(void *opaque, hwaddr addr, uint64_t val64,
case R_DATA_IN_2:
case R_DATA_IN_3:
r->data_in[reg - R_DATA_IN_0] = val32;
set_bit(reg - R_DATA_IN_0, r->data_in_bm);
set_bit((int64_t)(reg - R_DATA_IN_0), r->data_in_bm);
if (ot_aes_is_data_in_ready(r)) {
ibex_irq_set(&s->clkmgr, (int)true);
ot_aes_pop(s);
Expand Down Expand Up @@ -1283,6 +1286,7 @@ static void ot_aes_init(Object *obj)
static void ot_aes_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
(void)data;

dc->reset = &ot_aes_reset;
device_class_set_props(dc, ot_aes_properties);
Expand Down
3 changes: 3 additions & 0 deletions hw/opentitan/ot_alert_earlgrey.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ static void ot_alert_eg_update_irqs(OtAlertEgState *s)
static uint64_t ot_alert_eg_regs_read(void *opaque, hwaddr addr, unsigned size)
{
OtAlertEgState *s = opaque;
(void)size;
OtAlertRegs *regs = s->regs;
uint32_t val32;

Expand Down Expand Up @@ -419,6 +420,7 @@ static void ot_alert_eg_regs_write(void *opaque, hwaddr addr, uint64_t val64,
unsigned size)
{
OtAlertEgState *s = opaque;
(void)size;
OtAlertRegs *regs = s->regs;
uint32_t val32 = (uint32_t)val64;

Expand Down Expand Up @@ -665,6 +667,7 @@ static void ot_alert_eg_init(Object *obj)
static void ot_alert_eg_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
(void)data;

dc->reset = &ot_alert_eg_reset;
device_class_set_props(dc, ot_alert_eg_properties);
Expand Down
10 changes: 7 additions & 3 deletions hw/opentitan/ot_aon_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,20 +130,21 @@ ot_aon_timer_ticks_to_ns(OtAonTimerState *s, uint32_t prescaler, uint32_t ticks)
if (ns > INT64_MAX) {
return INT64_MAX;
}
return ns;
return (int64_t)ns;
}

static uint32_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now)
{
uint32_t prescaler = FIELD_EX32(s->regs[R_WKUP_CTRL], WKUP_CTRL, PRESCALER);
return s->regs[R_WKUP_COUNT] +
ot_aon_timer_ns_to_ticks(s, prescaler, now - s->wkup_origin_ns);
ot_aon_timer_ns_to_ticks(s, prescaler,
(int64_t)(now - s->wkup_origin_ns));
}

static uint32_t ot_aon_timer_get_wdog_count(OtAonTimerState *s, uint64_t now)
{
return s->regs[R_WDOG_COUNT] +
ot_aon_timer_ns_to_ticks(s, 0u, now - s->wdog_origin_ns);
ot_aon_timer_ns_to_ticks(s, 0u, (int64_t)(now - s->wdog_origin_ns));
}

static int64_t ot_aon_timer_compute_next_timeout(OtAonTimerState *s,
Expand Down Expand Up @@ -288,6 +289,7 @@ static void ot_aon_timer_wdog_cb(void *opaque)
static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size)
{
OtAonTimerState *s = opaque;
(void)size;
uint32_t val32;

hwaddr reg = R32_OFF(addr);
Expand Down Expand Up @@ -340,6 +342,7 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
OtAonTimerState *s = opaque;
(void)size;
uint32_t val32 = (uint32_t)value;

hwaddr reg = R32_OFF(addr);
Expand Down Expand Up @@ -509,6 +512,7 @@ static void ot_aon_timer_init(Object *obj)
static void ot_aon_timer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
(void)data;

dc->reset = ot_aon_timer_reset;
device_class_set_props(dc, ot_aon_timer_properties);
Expand Down
Loading