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

New Reset API for Hart, Support for JTAG, DMI and JTAG Mailbox access #52

Merged
merged 17 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b25babd
[ot] scripts/opentitan: add support for command line extra options
rivos-eblot Dec 7, 2023
30c3b76
[ot] hw/riscv: fix missing configuration in OT Darjeeling machine
rivos-eblot Dec 11, 2023
eefb120
[ot] hw/riscv: ot_darjeeling: fix CTN initialization
rivos-eblot Dec 11, 2023
2270b84
[ot] jtag: create a JTAG/TAP bitbang controller
rivos-eblot Dec 11, 2023
143f0a2
[ot] hw/riscv: create RISC-V Debug device
rivos-eblot Nov 24, 2023
8762bb0
[ot] hw/riscv: ibex_common: add JTAG IDCODE macros
rivos-eblot Nov 10, 2023
4c2d839
[ot] hw/riscv: create RISC-V Debug Module Interface
rivos-eblot Dec 11, 2023
54ef93f
[ot] hw/riscv: ot_darjeeling: add DMI support
rivos-eblot Dec 11, 2023
b2e3b4b
[ot] hw/opentitan: ot_dev_proxy: move MEMTXATTRS macro to ot_common.h
rivos-eblot Dec 12, 2023
48efd06
[ot] hw/opentitan: ot_dm_tl: create a DM-to-TL bridge device.
rivos-eblot Dec 12, 2023
43852e0
[ot] hw/opentitan: ot_mbx: add aperture values
rivos-eblot Dec 12, 2023
778bb9a
[ot] hw/riscv: ot_darjeeling: add DM-to-TL bridge device.
rivos-eblot Dec 12, 2023
1ed34a0
[ot] hw/core: Use resettable API to maintain CPU on reset
rivos-eblot Nov 20, 2023
2f34a2d
[ot] hw/opentitan: ot_pwrmgr: use Resettable API to release Hart from…
rivos-eblot Nov 20, 2023
104460f
[ot] ot_earlgrey: use Resettable API to start Hart in reset
rivos-eblot Nov 20, 2023
902ca32
[ot] ot_darjeeling: use Resettable API to start Hart in reset
rivos-eblot Nov 20, 2023
3fec1e6
[ot] target/riscv: cpu: add a reset exit function to update resetvec …
rivos-eblot Nov 21, 2023
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
4 changes: 2 additions & 2 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,11 +689,11 @@ static inline bool cpu_handle_halt(CPUState *cpu)
return true;
}

cpu->halted = 0;
cpu->halted = cpu->on_reset;
}
#endif /* !CONFIG_USER_ONLY */

return false;
return cpu->on_reset;
}

static inline void cpu_handle_debug_exception(CPUState *cpu)
Expand Down
47 changes: 27 additions & 20 deletions docs/opentitan/pyot.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,19 @@
## Usage

````text
usage: pyot.py [-h] [-c JSON] [-w CSV] [-R] [-k SECONDS] [-v] [-d] [-q QEMU]
[-Q OPTS] [-m MACHINE] [-p DEVICE] [-L LOG_FILE] [-M LOG]
[-t TRACE] [-i N] [-r ELF] [-O RAW] [-o VMEM] [-f RAW] [-x file]
[-b file]
usage: pyot.py [-h] [-q QEMU] [-Q OPTS] [-m MACHINE] [-p DEVICE] [-L LOG_FILE]
[-M LOG] [-t TRACE] [-i N] [-s] [-T SECS] [-U] [-c JSON]
[-w CSV] [-K] [-r ELF] [-O RAW] [-o VMEM] [-f RAW] [-x file]
[-b file] [-R] [-k SECONDS] [-F TEST] [-v] [-d]

OpenTitan test sequencer
OpenTitan QEMU test sequencer.

options:
-h, --help show this help message and exit
-c JSON, --config JSON
path to configuration file
-w CSV, --result CSV path to output result file
-R, --summary show a result summary
-k SECONDS, --timeout SECONDS
exit after the specified seconds (default: 60 secs)
-F TEST, --filter TEST
Only run tests whose filename matches any defined filter (may be repeated)
-K, --keep-tmp Do not automatically remove temporary files and dirs on exit
-v, --verbose increase verbosity
-d, --debug enable debug mode

Virtual machine:
-q QEMU, --qemu QEMU path to qemu application (default: build/qemu-system-riscv32)
-q QEMU, --qemu QEMU path to qemu application (default: build/qemu-system-
riscv32)
-Q OPTS, --opts OPTS QEMU verbatim option (can be repeated)
-m MACHINE, --machine MACHINE
virtual machine (default to ot-earlgrey)
Expand All @@ -38,20 +28,37 @@ Virtual machine:
-M LOG, --log LOG log message types
-t TRACE, --trace TRACE
trace event definition file
-i N, --icount N virtual instruction counter with 2^N clock ticks per inst.
-i N, --icount N virtual instruction counter with 2^N clock ticks per
inst.
-s, --singlestep enable "single stepping" QEMU execution mode
-T SECS, --timeout-factor SECS
timeout factor
-U, --muxserial enable multiple virtual UARTs to be muxed into same host output channel
-U, --muxserial enable multiple virtual UARTs to be muxed into same
host output channel

Files:
-r ELF, --rom ELF ROM ELF file
-c JSON, --config JSON
path to configuration file
-w CSV, --result CSV path to output result file
-K, --keep-tmp Do not automatically remove temporary files and dirs
on exit
-r ELF, --rom ELF ROM file
-O RAW, --otp-raw RAW
OTP image file
-o VMEM, --otp VMEM OTP VMEM file
-f RAW, --flash RAW embedded Flash image file
-x file, --exec file rom extension or application
-b file, --boot file bootloader 0 file

Execution:
-R, --summary show a result summary
-k SECONDS, --timeout SECONDS
exit after the specified seconds (default: 60 secs)
-F TEST, --filter TEST
only run tests whose filename matches any defined
filter (may be repeated)
-v, --verbose increase verbosity
-d, --debug enable debug mode
````

This tool may be used in two ways, which can be combined:
Expand Down
25 changes: 23 additions & 2 deletions hw/core/cpu-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,34 @@ void cpu_reset(CPUState *cpu)
trace_cpu_reset(cpu->cpu_index);
}

static void cpu_common_reset_hold(Object *obj)
static void cpu_common_reset_enter(Object *obj, ResetType type)
{
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(cpu);
cpu->on_reset = true;

if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index);
qemu_log("CPU Reset Enter (CPU %d)\n", cpu->cpu_index);
log_cpu_state(cpu, cc->reset_dump_flags);
}
}

static void cpu_common_reset_exit(Object *obj)
{
CPUState *cpu = CPU(obj);
cpu->on_reset = false;
cpu->halted = 0;
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
CPUClass *cc = CPU_GET_CLASS(cpu);
qemu_log("CPU Reset Exit (CPU %d) PC:0x%" VADDR_PRIx "\n",
cpu->cpu_index, cc->get_pc(cpu));
}
cpu_resume(cpu);
}

static void cpu_common_reset_hold(Object *obj)
{
CPUState *cpu = CPU(obj);

cpu->interrupt_request = 0;
cpu->halted = cpu->start_powered_off;
Expand Down Expand Up @@ -270,7 +289,9 @@ static void cpu_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
rc->phases.enter = cpu_common_reset_enter;
rc->phases.hold = cpu_common_reset_hold;
rc->phases.exit = cpu_common_reset_exit;
cpu_class_init_props(dc);
/*
* Reason: CPUs still need special care by board code: wiring up
Expand Down
4 changes: 4 additions & 0 deletions hw/opentitan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ config OT_CSRNG
config OT_DEV_PROXY
bool

config OT_DM_TL
select RISCV_DEBUG
bool

config OT_DMA
select OT_ADDRESS_SPACE
bool
Expand Down
1 change: 1 addition & 0 deletions hw/opentitan/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ system_ss.add(when: 'CONFIG_OT_CLKMGR', if_true: files('ot_clkmgr.c'))
system_ss.add(when: 'CONFIG_OT_COMMON', if_true: files('ot_common.c'))
system_ss.add(when: 'CONFIG_OT_CSRNG', if_true: [files('ot_csrng.c'), libtomcrypt_dep])
system_ss.add(when: 'CONFIG_OT_DEV_PROXY', if_true: files('ot_dev_proxy.c'))
system_ss.add(when: 'CONFIG_OT_DM_TL', if_true: files('ot_dm_tl.c'))
system_ss.add(when: 'CONFIG_OT_DMA', if_true: [files('ot_dma.c'), libtomcrypt_dep])
system_ss.add(when: 'CONFIG_OT_EDN', if_true: files('ot_edn.c'))
system_ss.add(when: 'CONFIG_OT_ENTROPY_SRC', if_true: [files('ot_entropy_src.c'), libtomcrypt_dep])
Expand Down
13 changes: 1 addition & 12 deletions hw/opentitan/ot_dev_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "hw/core/cpu.h"
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/opentitan/ot_common.h"
#include "hw/opentitan/ot_dev_proxy.h"
#include "hw/opentitan/ot_mbx.h"
#include "hw/opentitan/ot_soc_proxy.h"
Expand Down Expand Up @@ -184,18 +185,6 @@ enum OtDevProxyErr {
#define PROXY_MAKE_UID(_uid_, _req_) \
(((_uid_) & ~(1u << 31u)) | (((uint32_t)(bool)(_req_)) << 31u))

#if defined(MEMTXATTRS_HAS_ROLE) && (MEMTXATTRS_HAS_ROLE != 0)
#define MEMTXATTRS_WITH_ROLE(_r_) \
(MemTxAttrs) \
{ \
.role = (_r_) \
}
#define MEMTXATTRS_GET_ROLE(_a_) ((_a_).unspecified ? 0xfu : (_a_).role);
#else
#define MEMTXATTRS_WITH_ROLE(_r_) MEMTXATTRS_UNSPECIFIED
#define MEMTXATTRS_GET_ROLE(_a_) ((_a_).unspecified ? 0xfu : 0x0)
#endif

static void ot_dev_proxy_send(OtDevProxyState *s, unsigned uid, int dir,
uint16_t command, const void *payload,
size_t length)
Expand Down
211 changes: 211 additions & 0 deletions hw/opentitan/ot_dm_tl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*
* QEMU OpenTitan Debug Module to TileLink bridge
*
* Copyright (c) 2023 Rivos, Inc.
*
* Author(s):
* Emmanuel Blot <eblot@rivosinc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "qemu/osdep.h"
#include <stdint.h>
#include "qemu/log.h"
#include "qapi/error.h"
#include "exec/memory.h"
#include "hw/hw.h"
#include "hw/opentitan/ot_address_space.h"
#include "hw/opentitan/ot_common.h"
#include "hw/opentitan/ot_dm_tl.h"
#include "hw/qdev-properties-system.h"
#include "hw/qdev-properties.h"
#include "hw/registerfields.h"
#include "hw/riscv/debug.h"
#include "hw/riscv/dmi.h"
#include "hw/riscv/ibex_common.h"
#include "hw/sysbus.h"
#include "trace.h"

/** Debug Module */
struct OtDMTLState {
RISCVDebugDeviceState parent;
AddressSpace *as; /* Hart address space */
hwaddr tl_offset;
uint32_t value;
MemTxAttrs attrs;
bool dmi_ok; /* DMI is available */

RISCVDMIState *dmi;
SysBusDevice *tl_dev;
char *tl_as_name;
uint64_t tl_base;
uint32_t dmi_addr;
unsigned dmi_size;
uint8_t role;
};

/* -------------------------------------------------------------------------- */
/* DMI interface implementation */
/* -------------------------------------------------------------------------- */

static RISCVDebugResult
ot_dm_tl_write_rq(RISCVDebugDeviceState *dev, uint32_t addr, uint32_t value)
{
OtDMTLState *dmtl = OT_DM_TL(dev);

if (addr >= dmtl->dmi_size) {
trace_ot_dm_tl_invalid_addr(addr);
return RISCV_DEBUG_FAILED;
}

/* store address for next read back */
dmtl->tl_offset = addr * sizeof(uint32_t);

MemTxResult res;

res = address_space_rw(dmtl->as, dmtl->tl_base + dmtl->tl_offset,
dmtl->attrs, &value, sizeof(value), true);

trace_ot_dm_tl_update(addr, value, "write", res);

return (res == MEMTX_OK) ? RISCV_DEBUG_NOERR : RISCV_DEBUG_FAILED;
}

static RISCVDebugResult
ot_dm_tl_read_rq(RISCVDebugDeviceState *dev, uint32_t addr)
{
OtDMTLState *dmtl = OT_DM_TL(dev);

if (addr >= dmtl->dmi_size) {
trace_ot_dm_tl_invalid_addr(addr);
return RISCV_DEBUG_FAILED;
}

/* store address for next read back */
dmtl->tl_offset = addr * sizeof(uint32_t);

MemTxResult res;

res =
address_space_rw(dmtl->as, dmtl->tl_base + dmtl->tl_offset, dmtl->attrs,
&dmtl->value, sizeof(dmtl->value), false);

trace_ot_dm_tl_update(addr, 0, "read", res);

return (res == MEMTX_OK) ? RISCV_DEBUG_NOERR : RISCV_DEBUG_FAILED;
}

static uint32_t ot_dm_tl_read_value(RISCVDebugDeviceState *dev)
{
OtDMTLState *dmtl = OT_DM_TL(dev);

uint32_t value = dmtl->value;

trace_ot_dm_tl_capture(dmtl->tl_offset, value);

return value;
}

static Property ot_dm_tl_properties[] = {
DEFINE_PROP_LINK("dmi", OtDMTLState, dmi, TYPE_RISCV_DMI, RISCVDMIState *),
DEFINE_PROP_UINT32("dmi_addr", OtDMTLState, dmi_addr, 0),
DEFINE_PROP_UINT32("dmi_size", OtDMTLState, dmi_size, 0),
DEFINE_PROP_STRING("tl_as_name", OtDMTLState, tl_as_name),
DEFINE_PROP_UINT64("tl_addr", OtDMTLState, tl_base, 0),
DEFINE_PROP_LINK("tl_dev", OtDMTLState, tl_dev, TYPE_SYS_BUS_DEVICE,
SysBusDevice *),
DEFINE_PROP_UINT8("role", OtDMTLState, role, UINT8_MAX),
DEFINE_PROP_END_OF_LIST(),
};

static void ot_dm_tl_reset(DeviceState *dev)
{
OtDMTLState *dmtl = OT_DM_TL(dev);

g_assert(dmtl->dmi != NULL);
g_assert(dmtl->dmi_size);

dmtl->dmi_ok =
riscv_dmi_register_dm(DEVICE(dmtl->dmi), RISCV_DEBUG_DEVICE(dev),
dmtl->dmi_addr, dmtl->dmi_size);

if (dmtl->dmi_ok) {
Object *soc = OBJECT(dev)->parent;
Object *obj;
OtAddressSpaceState *oas;

g_assert(dmtl->tl_as_name);
obj = object_property_get_link(soc, dmtl->tl_as_name, &error_fatal);
oas = OBJECT_CHECK(OtAddressSpaceState, obj, TYPE_OT_ADDRESS_SPACE);
dmtl->as = ot_address_space_get(oas);
g_assert(dmtl->as);
}
}

static void ot_dm_tl_realize(DeviceState *dev, Error **errp)
{
OtDMTLState *dmtl = OT_DM_TL(dev);
(void)errp;

/* NOLINTNEXTLINE */
if (dmtl->role == UINT8_MAX) {
dmtl->attrs = MEMTXATTRS_UNSPECIFIED;
} else {
dmtl->attrs = MEMTXATTRS_WITH_ROLE(dmtl->role);
}
}

static void ot_dm_tl_init(Object *obj)
{
OtDMTLState *s = OT_DM_TL(obj);
(void)s;
}

static void ot_dm_tl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
(void)data;

dc->reset = &ot_dm_tl_reset;
dc->realize = &ot_dm_tl_realize;
device_class_set_props(dc, ot_dm_tl_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);

RISCVDebugDeviceClass *dmc = RISCV_DEBUG_DEVICE_CLASS(klass);
dmc->set_next_dm = NULL;
dmc->write_rq = &ot_dm_tl_write_rq;
dmc->read_rq = &ot_dm_tl_read_rq;
dmc->read_value = &ot_dm_tl_read_value;
}

static const TypeInfo ot_dm_tl_info = {
.name = TYPE_OT_DM_TL,
.parent = TYPE_RISCV_DEBUG_DEVICE,
.instance_init = &ot_dm_tl_init,
.instance_size = sizeof(OtDMTLState),
.class_init = &ot_dm_tl_class_init,
};

static void ot_dm_tl_register_types(void)
{
type_register_static(&ot_dm_tl_info);
}

type_init(ot_dm_tl_register_types);
Loading