kparzysz-quic commented on a change in pull request #5252: [RUNTIME] Initial implementation of Hexagon runtime support URL: https://github.com/apache/incubator-tvm/pull/5252#discussion_r404783723
########## File path: src/runtime/hexagon/target/hexagon_device_target.cc ########## @@ -0,0 +1,525 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef __ANDROID__ + +#include <unistd.h> + +#include <algorithm> +#include <map> +#include <memory> +#include <string> +#include <utility> + +#include "../hexagon_module.h" +#include "AEEStdErr.h" +#include "fastrpc/tvm_hexagon_remote.h" +#include "hexagon_dsprpcapi.h" +#include "hexagon_stubapi.h" +#include "hexagon_target_log.h" +#include "remote64.h" +#include "rpcmem.h" + +#pragma weak remote_session_control + +#define RPCMEM_HEAP 25 + +// All log messages start with "HexagonTarget::%s", where %s is replaced +// with the function name, so create macros that add that to avoid repetition. +// The downside is that the format string must be given as a string literal, +// but it seems to be a minor issue. +#define VA_EXPANDER(...) , ##__VA_ARGS__ +#define TVM_LOGD_HT(fmt, ...) \ + TVM_LOGD("HexagonTarget::%s: " fmt, __func__ VA_EXPANDER(__VA_ARGS__)) +#define TVM_LOGE_HT(fmt, ...) \ + TVM_LOGE("HexagonTarget::%s: " fmt, __func__ VA_EXPANDER(__VA_ARGS__)) + +namespace tvm { +namespace runtime { +namespace hexagon { + +static constexpr int kStackSize = 128 * 1024; // 128kB stack + +class HexagonTarget : public tvm::runtime::hexagon::Device { + public: + HexagonTarget() {} + ~HexagonTarget() final {} + void* Alloc(unsigned size, unsigned align) final; + void Free(void* ptr) final; + void* AllocVtcm(unsigned size, unsigned align) final; + void FreeVtcm(void* ptr) final; + void CopyDeviceToDevice(void* dst, const void* src, unsigned len) final; + void CopyDeviceToHost(void* host_dst, const void* src, unsigned len) final; + void CopyHostToDevice(void* dst, const void* host_src, unsigned len) final; + void* Load(const std::string& data, const std::string& fmt) final; + void Unload(void* mod) final; + void* Resolve(const std::string& sym) final; + void Call(void* func, uint32_t* scalar, unsigned scalar_num, uint32_t* stack, + unsigned stack_num) final; + + private: + std::pair<void*, size_t> AddAddrMapping(const void* dsp_addr, + void* apps_addr, size_t size); + std::pair<void*, size_t> GetAppsAddr(const void* dsp_addr, bool exact) const; + void RemoveAddrMapping(const void* dsp_addr); + int OpenDomainChannel(bool set_unsigned_pd); + int CloseDomainChannel(); + void ReleaseLibrary(); + void FreeMemoryBeforeChannelClose(); + + // Mapping from a DSP address to a pair <apps address, buffer size>. + // Using void* pointers is ok, since DSP pointers will always fit + // in apps's pointers, i.e. sizeof_dsp(void*) <= sizeof_apps(void*). + std::map<const void*, std::pair<void*, size_t>> dsp_to_apps_; + std::map<const void*, std::pair<void*, size_t>> vtcm_addr_; + remote_handle64 domain_channel_handle_ = AEE_EUNKNOWN; + tvm_hexagon_remote_handle_t module_pointer_ = AEE_EUNKNOWN; + uint64_t count_channel_open_ = 0; + // Global lock, used for all critical sections. This can be refined + // in the future. + mutable std::mutex crit_section_; +}; + +std::shared_ptr<Device> CreateHexagonTarget() { + return std::make_shared<HexagonTarget>(); +} + +std::pair<void*, size_t> HexagonTarget::AddAddrMapping(const void* dsp_addr, + void* apps_addr, + size_t size) { + crit_section_.lock(); + auto p = dsp_to_apps_.insert({dsp_addr, {apps_addr, size}}); + crit_section_.unlock(); + if (!p.second) { + TVM_LOGE_HT( + "failed to insert address mapping: dsp:%p -> apps:%p, size:%zu", + dsp_addr, apps_addr, size); + return std::make_pair(nullptr, 0); + } + TVM_LOGD_HT("added address mapping: dsp:%p -> apps:%p, size:%zu", dsp_addr, + apps_addr, size); + return p.first->second; +} + +void HexagonTarget::RemoveAddrMapping(const void* dsp_addr) { + crit_section_.lock(); + auto f = dsp_to_apps_.find(dsp_addr); + if (f == dsp_to_apps_.end()) { + TVM_LOGE_HT("failed to remove address mapping for dsp:%p", dsp_addr); + crit_section_.unlock(); + return; + } + dsp_to_apps_.erase(f); + crit_section_.unlock(); +} + +std::pair<void*, size_t> HexagonTarget::GetAppsAddr(const void* dsp_addr, + bool exact) const { + struct AutoUnlock { + explicit AutoUnlock(std::mutex& m) : m(m) {} + ~AutoUnlock() { m.unlock(); } + std::mutex& m; + }; + + crit_section_.lock(); + AutoUnlock u(crit_section_); + + // If the address is in the map, simply return the result. + auto f = dsp_to_apps_.find(dsp_addr); + if (f != dsp_to_apps_.end()) return f->second; + // If exact mapping is requested, then it hasn't been found. + if (exact) return std::make_pair(nullptr, 0); + + // If the address is not in the map, maybe it points to somewhere in the + // interior of a mapped buffer. + uintptr_t dsp_v = reinterpret_cast<uintptr_t>(dsp_addr); + for (const auto& v : dsp_to_apps_) { + uintptr_t dsp_k = reinterpret_cast<uintptr_t>(v.first); + size_t size = v.second.second; + if (dsp_v >= dsp_k && dsp_v < dsp_k + size) { + uintptr_t apps_k = reinterpret_cast<uintptr_t>(v.second.first); + size_t offset = dsp_v - dsp_k; + uintptr_t apps_v = apps_k + offset; + return std::make_pair(reinterpret_cast<void*>(apps_v), size - offset); + } + } + TVM_LOGE_HT("failed to locate apps address for dsp:%p", dsp_addr); + return std::make_pair(nullptr, 0); +} + +int HexagonTarget::OpenDomainChannel(bool use_unsigned_pd) { + if (domain_channel_handle_ != AEE_EUNKNOWN) return AEE_SUCCESS; + + const DspRpcAPI* dsp_api = DspRpcAPI::Global(); + const StubAPI* stub_api = StubAPI::Global(); + + stub_api->rpcmem_init_ptr()(); Review comment: I can set it to false, would you prefer that? I don't think there is a way to make it a parameter that the user can provide at run time. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services