From 67add21188c70240b8966cdd707b03c02bd41a56 Mon Sep 17 00:00:00 2001 From: Mikael Olsson Date: Wed, 31 May 2023 19:00:48 +0200 Subject: 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 --- applications/message_handler_openamp/main.cpp | 17 +++- .../message_handler_openamp/remoteproc.cpp | 107 ++++++++++----------- .../message_handler_openamp/remoteproc.hpp | 85 +++++++++------- 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(); - auto rproc = std::make_shared(mailbox, resourceTable.table, sizeof(resourceTable), *mem); + auto rproc = std::make_shared(mailbox, resourceTable.table, sizeof(resourceTable)); auto messageHandler = std::make_shared(*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 - * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -26,66 +25,39 @@ #include -/***************************************************************************** - * MetalIO - *****************************************************************************/ - -extern "C" { - -__attribute__((weak)) void *ethosu_phys_to_virt(const uint64_t pa) { - return reinterpret_cast(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, ®ion); - - metal_io_init(®ion, - reinterpret_cast(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 ®ion) { -unsigned long MetalIO::physToOffset(metal_io_region *io, metal_phys_addr_t pa) { - auto offset = reinterpret_cast(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, ®ion); + metal_io_init(®ion, (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(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(&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(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->priv); + struct fw_rsc_mapping *mapping = static_cast(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 - * * 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 @@ -58,32 +93,13 @@ struct ResourceTable { fw_rsc_carveout carveout; } __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; -- cgit v1.2.1