aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Olsson <mikael.olsson@arm.com>2023-05-31 19:00:48 +0200
committerMikael Olsson <mikael.olsson@arm.com>2023-09-28 11:53:42 +0200
commit67add21188c70240b8966cdd707b03c02bd41a56 (patch)
tree77219fcd0095e060063ac90ce0afbbc18b052cb3
parentfdd8b41d12a8fd729619dee12080e65ec151865c (diff)
downloadethos-u-core-platform-67add21188c70240b8966cdd707b03c02bd41a56.tar.gz
Add resource table entry for address translation
To avoid having to use a hardcoded memory map to translate between the Linux physical addresses and device addresses, a new entry type has been added to the resource table where the host can provide the memory map to use for the translation. Change-Id: I668bba3aeac27c358647c969c5504326e1c91d24 Signed-off-by: Mikael Olsson <mikael.olsson@arm.com>
-rw-r--r--applications/message_handler_openamp/main.cpp17
-rw-r--r--applications/message_handler_openamp/remoteproc.cpp107
-rw-r--r--applications/message_handler_openamp/remoteproc.hpp85
3 files changed, 114 insertions, 95 deletions
diff --git a/applications/message_handler_openamp/main.cpp b/applications/message_handler_openamp/main.cpp
index 7b755b9..62bdc97 100644
--- a/applications/message_handler_openamp/main.cpp
+++ b/applications/message_handler_openamp/main.cpp
@@ -84,12 +84,24 @@ __attribute__((section(".resource_table"))) ResourceTable resourceTable = {
},
// Offset
{
+ offsetof(ResourceTable, mapping),
#if defined(REMOTEPROC_TRACE_BUFFER)
offsetof(ResourceTable, trace),
#endif
offsetof(ResourceTable, vdev),
offsetof(ResourceTable, carveout),
- },
+ },
+ // Mappings
+ {
+ RSC_MAPPING,
+ ResourceTable::NUM_RANGES,
+ {}
+ },
+ // Ranges
+ {
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
// Trace buffer
#if defined(REMOTEPROC_TRACE_BUFFER)
{
@@ -163,8 +175,7 @@ void mailboxIrqHandler() {
int main() {
printf("Ethos-U Message Handler OpenAMP\n");
- auto mem = std::make_shared<MetalIO>();
- auto rproc = std::make_shared<RProc>(mailbox, resourceTable.table, sizeof(resourceTable), *mem);
+ auto rproc = std::make_shared<RProc>(mailbox, resourceTable.table, sizeof(resourceTable));
auto messageHandler = std::make_shared<MessageHandler>(*rproc, "ethos-u-0.0");
printf("TFLM arena. pa=%" PRIx32 ", da=%" PRIx32 ", len=%" PRIx32 "\n",
diff --git a/applications/message_handler_openamp/remoteproc.cpp b/applications/message_handler_openamp/remoteproc.cpp
index f355634..8fda69b 100644
--- a/applications/message_handler_openamp/remoteproc.cpp
+++ b/applications/message_handler_openamp/remoteproc.cpp
@@ -1,6 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
- *
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
@@ -26,66 +25,39 @@
#include <ethosu_log.h>
-/*****************************************************************************
- * MetalIO
- *****************************************************************************/
-
-extern "C" {
-
-__attribute__((weak)) void *ethosu_phys_to_virt(const uint64_t pa) {
- return reinterpret_cast<void *>(pa);
-}
-}
-
-MetalIO::MetalIO() :
- ops{.read = nullptr,
- .write = nullptr,
- .block_read = nullptr,
- .block_write = nullptr,
- .block_set = nullptr,
- .close = nullptr,
- .offset_to_phys = nullptr,
- .phys_to_offset = physToOffset} {
- remoteproc_init_mem(&mem, "shm", 0, 0, 0xffffffff, &region);
-
- metal_io_init(&region,
- reinterpret_cast<void *>(0), /* virt */
- &mem.pa, /* physmap */
- 0xffffffff, /* size */
- -1L, /* pagemask */
- 0, /* attributes */
- &ops); /* ops */
-}
-
-remoteproc_mem *MetalIO::operator&() {
- return &mem;
-}
+namespace {
+void setupRProcMem(remoteproc &rproc,
+ metal_phys_addr_t pa,
+ metal_phys_addr_t da,
+ size_t size,
+ remoteproc_mem &mem,
+ metal_io_region &region) {
-unsigned long MetalIO::physToOffset(metal_io_region *io, metal_phys_addr_t pa) {
- auto offset = reinterpret_cast<unsigned long>(ethosu_phys_to_virt(pa));
- LOG_DEBUG("Translate PA to offset. pa=%lx, offset=%lx", pa, offset);
- return offset;
+ remoteproc_init_mem(&mem, nullptr, pa, da, size, &region);
+ metal_io_init(&region, (void *)da, &mem.pa, size, -1, 0, nullptr);
+ remoteproc_add_mem(&rproc, &mem);
}
+}; // namespace
/*****************************************************************************
* RProc
*****************************************************************************/
-RProc::RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize, MetalIO &_mem) :
- mailbox(_mailbox), mem(_mem),
+RProc::RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize) :
+ mailbox(_mailbox),
ops{
- .init = init, // initialize the remoteproc instance
- .remove = remove, // remove the remoteproc instance
- .mmap = nullptr, // memory mapped the memory with physical address as input
- .handle_rsc = nullptr, // handle the vendor specific resource
- .config = nullptr, // configure the remoteproc to make it ready to load and run executable
- .start = nullptr, // kick the remoteproc to run application
+ .init = init, // initialize the remoteproc instance
+ .remove = remove, // remove the remoteproc instance
+ .mmap = nullptr, // memory mapped the memory with physical address as input
+ .handle_rsc = handle_rsc, // handle the vendor specific resource
+ .config = nullptr, // configure the remoteproc to make it ready to load and run executable
+ .start = nullptr, // kick the remoteproc to run application
.stop = nullptr, // stop the remoteproc from running application, the resource such as memory may not be off.
.shutdown = nullptr, // shutdown the remoteproc and release its resources.
.notify = notify, // notify the remote
.get_mem = nullptr, // get remoteproc memory I/O region.
},
- vdev(nullptr), notifySemaphore(xSemaphoreCreateBinary()) {
+ vdev(nullptr), mems(), regions(), notifySemaphore(xSemaphoreCreateBinary()) {
mailbox.registerCallback(mailboxCallback, static_cast<void *>(this));
if (!remoteproc_init(&rproc, &ops, this)) {
@@ -93,6 +65,12 @@ RProc::RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize
abort();
}
+ // Setup memory region for resource table
+ const metal_phys_addr_t rsc_addr = reinterpret_cast<metal_phys_addr_t>(&table);
+ // No translation is needed for rsc_addr because it already contains the DA
+ // so PA is set to DA
+ setupRProcMem(rproc, rsc_addr, rsc_addr, tableSize, rsc_mem, rsc_region);
+
int ret = remoteproc_set_rsc_table(&rproc, &table, tableSize);
if (ret) {
LOG_ERR("Failed to set resource table. ret=%d", ret);
@@ -148,15 +126,33 @@ void RProc::notifyTask(void *param) {
struct remoteproc *RProc::init(remoteproc *rproc, const remoteproc_ops *ops, void *arg) {
LOG_DEBUG("");
- auto _this = static_cast<RProc *>(arg);
-
rproc->ops = ops;
rproc->priv = arg;
- remoteproc_add_mem(rproc, &_this->mem);
return rproc;
}
+int RProc::handle_rsc(remoteproc *rproc, void *rsc, size_t len) {
+ auto _this = static_cast<RProc *>(rproc->priv);
+ struct fw_rsc_mapping *mapping = static_cast<fw_rsc_mapping *>(rsc);
+
+ if (mapping->type != RSC_MAPPING) {
+ LOG_ERR("Unknown resource type %" PRIu32, mapping->type);
+ return -RPROC_ERR_RSC_TAB_NS;
+ }
+
+ for (uint32_t i = 0; i < mapping->num_ranges; ++i) {
+ const fw_rsc_map_range *range = &mapping->range[i];
+ if (range->len == 0) {
+ LOG_DEBUG("Ignored zero length memory map range[%" PRIu32 "]", i);
+ continue;
+ }
+ setupRProcMem(*rproc, range->pa, range->da, range->len, _this->mems[i], _this->regions[i]);
+ }
+
+ return 0;
+}
+
void RProc::remove(remoteproc *rproc) {
LOG_DEBUG("");
}
@@ -174,14 +170,15 @@ int RProc::notify(remoteproc *rproc, uint32_t id) {
*****************************************************************************/
Rpmsg::Rpmsg(RProc &rproc, const char *const name) {
+ struct virtio_device *vdev = rproc.getVDev();
- metal_io_region *region = remoteproc_get_io_with_name(rproc.getRProc(), "shm");
- if (!region) {
- LOG_ERR("Failed to get shared mem region");
+ if (vdev->vrings_num != ResourceTable::NUM_VRINGS) {
+ LOG_ERR("Invalid number of vrings");
abort();
}
- if (rpmsg_init_vdev(&rvdev, rproc.getVDev(), nullptr, region, nullptr)) {
+ // Vdev can use the same IO region for translations as the vring
+ if (rpmsg_init_vdev(&rvdev, vdev, nullptr, vdev->vrings_info[0].io, nullptr)) {
LOG_ERR("Failed to initialize rpmsg vdev");
abort();
}
diff --git a/applications/message_handler_openamp/remoteproc.hpp b/applications/message_handler_openamp/remoteproc.hpp
index eec7b44..090a3ea 100644
--- a/applications/message_handler_openamp/remoteproc.hpp
+++ b/applications/message_handler_openamp/remoteproc.hpp
@@ -1,6 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
- *
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
@@ -36,13 +35,47 @@
* Resource table
*****************************************************************************/
+static constexpr uint32_t RSC_MAPPING = RSC_VENDOR_START + 1;
+
+/**
+ * struct fw_rsc_map_range - memory map range
+ * @da: Start device address of the memory address range
+ * @pa: Start physical address of the memory address range
+ * @len: length of memory address range
+ *
+ * Memory range to translate between physical and device addresses.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_map_range {
+ uint32_t da;
+ uint32_t pa;
+ uint32_t len;
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_mapping - memory map for address translation
+ * @type: RSC_MAPPING
+ * @num_ranges: Number of ranges in the memory map
+ * @range: Array of the ranges in the memory map
+ *
+ * This resource entry requests the host to provide information for how to
+ * translate between physical and device addresses.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_mapping {
+ uint32_t type;
+ uint8_t num_ranges;
+ struct fw_rsc_map_range range[0];
+} METAL_PACKED_END;
+
struct ResourceTable {
static constexpr uint32_t VERSION = 1;
#if defined(REMOTEPROC_TRACE_BUFFER)
- static constexpr uint32_t NUM_RESOURCES = 3;
+ static constexpr uint32_t NUM_RESOURCES = 4;
#else
- static constexpr uint32_t NUM_RESOURCES = 2;
+ static constexpr uint32_t NUM_RESOURCES = 3;
#endif
+ static constexpr uint32_t NUM_RANGES = 2;
static constexpr uint32_t NUM_VRINGS = 2;
static constexpr uint32_t VRING_ALIGN = 0x100;
static constexpr uint32_t VRING_SIZE = 0x08;
@@ -50,6 +83,8 @@ struct ResourceTable {
resource_table table;
uint32_t offset[NUM_RESOURCES];
+ fw_rsc_mapping mapping;
+ fw_rsc_map_range range[NUM_RANGES];
#if defined(REMOTEPROC_TRACE_BUFFER)
fw_rsc_trace trace;
#endif
@@ -59,31 +94,12 @@ struct ResourceTable {
} __attribute__((packed));
/*****************************************************************************
- * MetalIO
- *****************************************************************************/
-
-class MetalIO {
-public:
- MetalIO();
-
- remoteproc_mem *operator&();
-
-private:
- static metal_phys_addr_t offsetToPhys(metal_io_region *io, unsigned long offset);
- static unsigned long physToOffset(metal_io_region *io, metal_phys_addr_t phys);
-
- metal_io_ops ops;
- metal_io_region region;
- remoteproc_mem mem;
-};
-
-/*****************************************************************************
* RProc
*****************************************************************************/
class RProc {
public:
- RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize, MetalIO &_mem);
+ RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize);
~RProc();
remoteproc *getRProc();
@@ -99,30 +115,25 @@ private:
// Remote proc ops
static struct remoteproc *init(remoteproc *rproc, const remoteproc_ops *ops, void *arg);
static void remove(remoteproc *rproc);
- static void *mmap(remoteproc *rproc,
- metal_phys_addr_t *pa,
- metal_phys_addr_t *da,
- size_t size,
- unsigned int attribute,
- metal_io_region **io);
+ static int handle_rsc(struct remoteproc *rproc, void *rsc, size_t len);
static int notify(remoteproc *rproc, uint32_t id);
- static struct remoteproc_mem *getMem(remoteproc *rproc,
- const char *name,
- metal_phys_addr_t pa,
- metal_phys_addr_t da,
- void *va,
- size_t size,
- remoteproc_mem *buf);
// IRQ notification
Mailbox::Mailbox &mailbox;
// Remoteproc
- MetalIO &mem;
remoteproc rproc;
remoteproc_ops ops;
virtio_device *vdev;
+ // Resource table memory region
+ remoteproc_mem rsc_mem;
+ metal_io_region rsc_region;
+
+ // Host provided memory regions
+ remoteproc_mem mems[ResourceTable::NUM_RANGES];
+ metal_io_region regions[ResourceTable::NUM_RANGES];
+
// FreeRTOS
SemaphoreHandle_t notifySemaphore;
TaskHandle_t notifyHandle;