56 :
public tlm::tlm_initiator_socket<BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>,
57 public tlm::tlm_bw_transport_if<>
61 std::vector<std::pair<sc_dt::uint64, sc_dt::uint64>> m_ranges;
62 std::thread::id m_thread_id;
67 using TlmInitiatorSocket = tlm::tlm_initiator_socket<
BUSWIDTH, tlm::tlm_base_protocol_types, 1,
68 sc_core::SC_ZERO_OR_MORE_BOUND>;
69 using TlmPayload = tlm::tlm_generic_payload;
70 using MemTxResult = qemu::MemoryRegionOps::MemTxResult;
84 std::atomic<bool> m_finished =
false;
86 std::shared_ptr<qemu::AddressSpace> m_as;
87 std::shared_ptr<qemu::MemoryListener> m_listener;
88 std::map<uint64_t, std::shared_ptr<qemu::IOMMUMemoryRegion>> m_mmio_mrs;
93 std::shared_ptr<qemu::MemoryRegion> m_root;
100 std::map<DmiRegionAliasKey, DmiRegionAlias::Ptr> m_dmi_aliases;
101 using AliasesIterator = std::map<DmiRegionAliasKey, DmiRegionAlias::Ptr>::iterator;
112 const auto&
e =
it->second;
126 trans.set_data_ptr(
reinterpret_cast<unsigned char*
>(
val));
127 trans.set_data_length(size);
128 trans.set_streaming_width(size);
129 trans.set_byte_enable_length(0);
130 trans.set_dmi_allowed(
false);
131 trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
133 m_initiator.initiator_customize_tlm_payload(
trans);
136 void add_dmi_mr_alias(DmiRegionAlias::Ptr
alias)
141 alias->set_installed();
144 void del_dmi_mr_alias(
const DmiRegionAlias::Ptr
alias)
146 if (!
alias->is_installed()) {
150 m_r->m_root->del_subregion(
alias->get_alias_mr());
179 std::lock_guard<std::mutex>
lock(m_mutex);
187 te->translated_addr = (
it->second.translated_addr & ~(
it->second.addr_mask)) +
188 (
addr & (
it->second.addr_mask));
191 (
"FAST translate for 0x{:x} : 0x{:x}->0x{:x} (mask 0x{:x}) perm={}",
addr,
te->iova,
192 te->translated_addr,
te->addr_mask,
te->perm);
215 if (
lu_dmi.has_dmi(gs::tlm_dmi_ex::dmi_iommu)) {
225 (
"Adding IOMMU DMI Region start 0x{:x} - 0x{:x}",
lu_dmi_data.get_start_address(),
231 te->target_as =
iommumr->m_as_te->get_ptr();
233 te->addr_mask = mask;
238 te->perm = (qemu::IOMMUMemoryRegion::IOMMUAccessFlags)
ldmi_data.get_granted_access();
241 (
"Translate IOMMU 0x{:x}->0x{:x} (mask 0x{:x})",
te->iova,
te->translated_addr,
te->addr_mask);
251 alias->set_installed();
254 auto mask =
iommumr->min_page_sz;
255 te->target_as =
iommumr->m_as_io->get_ptr();
256 te->addr_mask = mask;
259 te->perm = (qemu::IOMMUMemoryRegion::IOMMUAccessFlags)
ldmi_data.get_granted_access();
262 (
"Translate 1-1 passthrough 0x{:x}->0x{:x} (mask 0x{:x})",
te->iova,
te->translated_addr,
266 std::lock_guard<std::mutex>
lock(m_mutex);
274 (
"Caching TE at addr 0x{:x} (mask {:x})",
addr &
~te->addr_mask,
te->addr_mask);
280 te->target_as =
iommumr->m_as_io->get_ptr();
281 te->addr_mask = (1 <<
iommumr->min_page_sz) - 1;
284 te->perm = qemu::IOMMUMemoryRegion::IOMMU_RW;
287 SCP_FATAL(())(
"Trying to add a 1-1 mapping over an existing mapping");
293 (
"Translate 1-1 limited passthrough 0x{:x}->0x{:x} (mask 0x{:x})",
te->iova,
te->translated_addr,
342 tlm::tlm_dmi dmi_data;
349 for (
auto m : m_mmio_mrs) {
351 auto mr_end =
m.first +
m.second->get_size() - 1;
355 if (
it !=
m.second->m_mapped_te.end()) {
358 it->second.addr_mask);
359 m.second->iommu_unmap(&(
it->second));
360 m.second->m_mapped_te.erase(
it);
362 SCP_TRACE(())(
"Suspected MMIO Region(s) removed arround address 0x{:x}",
addr);
367 SCP_INFO(()) <<
"DMI request for address 0x" << std::hex <<
trans.get_address();
374 bool dmi_valid = (*this)->get_direct_mem_ptr(
trans, dmi_data);
377 SCP_INFO(())(
"No DMI available for {:x}",
trans.get_address());
381 if (
u_dmi.has_dmi(gs::tlm_dmi_ex::dmi_mapped)) {
382 tlm::tlm_dmi
first_map =
u_dmi.get_first(gs::tlm_dmi_ex::dmi_mapped);
385 if (
u_dmi.has_dmi(gs::tlm_dmi_ex::dmi_nomap)) {
402 if (
u_dmi.has_dmi(gs::tlm_dmi_ex::dmi_iommu)) {
404 SCP_INFO(())(
"IOMMU DMI available for {:x}",
trans.get_address());
407 tlm::tlm_dmi
first_map =
u_dmi.get_first(gs::tlm_dmi_ex::dmi_mapped);
411 auto itr = m_mmio_mrs.find(start);
412 if (
itr == m_mmio_mrs.end()) {
418 invalidate_single_range(start, start + size - 1);
421 (
"Adding IOMMU for VA 0x{:x} [0x{:x} - 0x{:x}]",
trans.get_address(), start, start + size - 1);
423 using namespace std::placeholders;
424 qemu::MemoryRegionOpsPtr
ops;
425 ops = m_inst.
get().memory_region_ops_new();
426 ops->set_read_callback(std::bind(&QemuInitiatorSocket::qemu_io_read,
this,
_1,
_2,
_3,
_4));
427 ops->set_write_callback(std::bind(&QemuInitiatorSocket::qemu_io_write,
this,
_1,
_2,
_3,
_4));
428 ops->set_max_access_size(8);
430 auto iommumr = std::make_shared<qemu::IOMMUMemoryRegion>(
435 qemu::IOMMUMemoryRegion::IOMMUAccessFlags flags,
438 std::lock_guard<std::mutex>
lock(m_mutex);
441 m_r->m_root->add_subregion(*
iommumr, start);
450 (
"Memory request should be directed via MMIO interface {:x} {:x}", start,
trans.get_address());
469 SCP_INFO(()) <<
"DMI Adding for address 0x" << std::hex <<
trans.get_address();
486 if (m_dmi_aliases.size() > MAX_MAP) {
487 SCP_FATAL(())(
"Too many DMI regions requested, consider using an IOMMU");
489 uint64_t start = dmi_data.get_start_address();
490 uint64_t end = dmi_data.get_end_address();
492 if (0 == m_dmi_aliases.count(start)) {
493 SCP_INFO(()) <<
"Adding DMI for range [0x" << std::hex << dmi_data.get_start_address() <<
"-0x" << std::hex
494 << dmi_data.get_end_address() <<
"]";
498 m_dmi_aliases[start] =
alias;
499 add_dmi_mr_alias(m_dmi_aliases[start]);
501 SCP_INFO(())(
"Already have DMI for 0x{:x}", start);
506 void check_qemu_mr_hint(TlmPayload&
trans)
513 if (
ext ==
nullptr) {
519 if (
target_mr.get_inst_id() != m_dev.get_inst_id()) {
531 void do_regular_access(TlmPayload&
trans)
533 using sc_core::sc_time;
536 sc_time
now = m_initiator.initiator_get_local_time();
538 m_inst.
get().unlock_iothread();
540 m_inst.
get().lock_iothread();
546 check_qemu_mr_hint(
trans);
547 if (
trans.is_dmi_allowed()) {
551 m_initiator.initiator_set_local_time(
now);
554 void do_debug_access(TlmPayload&
trans)
556 m_inst.
get().unlock_iothread();
558 m_inst.
get().lock_iothread();
561 void do_direct_access(TlmPayload&
trans)
563 sc_core::sc_time
now = m_initiator.initiator_get_local_time();
571 if (m_finished)
return qemu::MemoryRegionOps::MemTxError;
579 do_direct_access(
trans);
581 if (!m_inst.g_rec_qemu_io_lock.try_lock() && !is_on_sysc()) {
587 m_inst.
get().unlock_iothread();
588 m_inst.g_rec_qemu_io_lock.lock();
589 m_inst.
get().lock_iothread();
594 if (reentrancy > 1) {
595 do_direct_access(
trans);
596 }
else if (
attrs.debug) {
597 do_debug_access(
trans);
599 do_regular_access(
trans);
603 m_inst.g_rec_qemu_io_lock.unlock();
605 m_initiator.initiator_tidy_tlm_payload(
trans);
607 switch (
trans.get_response_status()) {
608 case tlm::TLM_OK_RESPONSE:
609 return qemu::MemoryRegionOps::MemTxOK;
611 case tlm::TLM_ADDRESS_ERROR_RESPONSE:
612 return qemu::MemoryRegionOps::MemTxDecodeError;
615 return qemu::MemoryRegionOps::MemTxError;
622 return qemu_io_access(tlm::TLM_READ_COMMAND,
addr,
val, size,
attrs);
627 return qemu_io_access(tlm::TLM_WRITE_COMMAND,
addr, &
val, size,
attrs);
630 bool is_on_sysc()
const {
return std::this_thread::get_id() == m_thread_id; }
633 : TlmInitiatorSocket(name)
639 SCP_DEBUG(()) <<
"QemuInitiatorSocket constructor";
640 TlmInitiatorSocket::bind(*
static_cast<tlm::tlm_bw_transport_if<>*
>(
this));
645 using namespace std::placeholders;
648 qemu::MemoryRegionOpsPtr
ops;
650 m_r =
new m_mem_obj(inst);
651 ops = inst.memory_region_ops_new();
653 ops->set_read_callback(std::bind(&QemuInitiatorSocket::qemu_io_read,
this,
_1,
_2,
_3,
_4));
654 ops->set_write_callback(std::bind(&QemuInitiatorSocket::qemu_io_write,
this,
_1,
_2,
_3,
_4));
655 ops->set_max_access_size(8);
657 m_r->m_root->init_io(
dev, TlmInitiatorSocket::name(), std::numeric_limits<uint64_t>::max(),
ops);
658 dev.set_prop_link(
prop, *m_r->m_root);
663 void end_of_simulation()
675 m_r->m_root->removeSubRegions();
687 if (m_finished)
return;
689 SCP_DEBUG(()) <<
"Mapping request for address [0x" << std::hex <<
addr <<
"-0x" <<
addr +
len - 1 <<
"]";
695 trans.set_dmi_allowed(
true);
703 SCP_INFO(()) <<
"0x" << std::hex <<
current_addr <<
" mapped [0x" << dmi_data.get_start_address() <<
"-0x"
704 << dmi_data.get_end_address() <<
"]";
714 m_initiator.initiator_tidy_tlm_payload(
trans);
719 using namespace std::placeholders;
722 qemu::MemoryRegionOpsPtr
ops;
723 ops = inst.memory_region_ops_new();
725 ops->set_read_callback(std::bind(&QemuInitiatorSocket::qemu_io_read,
this,
_1,
_2,
_3,
_4));
726 ops->set_write_callback(std::bind(&QemuInitiatorSocket::qemu_io_write,
this,
_1,
_2,
_3,
_4));
727 ops->set_max_access_size(8);
730 system_memory->init_io(
dev, TlmInitiatorSocket::name(), std::numeric_limits<uint64_t>::max() - 1,
ops);
733 m_as = inst.address_space_get_system_memory();
736 m_as->update_topology();
742 m_listener = inst.memory_listener_new();
743 m_listener->set_map_callback(std::bind(&QemuInitiatorSocket::qemu_map,
this,
_1,
_2,
_3));
744 m_listener->register_as(m_as);
750 virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload&
trans, tlm::tlm_phase&
phase,
755 return tlm::TLM_COMPLETED;
758 virtual AliasesIterator remove_alias(AliasesIterator
it)
760 DmiRegionAlias::Ptr r =
it->second;
777 assert(r->is_installed());
800 return m_dmi_aliases.erase(
it);
808 if (
it != m_dmi_aliases.begin()) {
815 while (
it != m_dmi_aliases.end()) {
816 DmiRegionAlias::Ptr r =
it->second;
829 it = remove_alias(
it);
831 SCP_DEBUG(()) <<
"Invalidated region [0x" << std::hex << r->get_start() <<
", 0x" << std::hex
832 << r->get_end() <<
"]";
836 void invalidate_ranges_safe_cb()
838 if (m_finished)
return;
839 std::lock_guard<std::mutex>
lock(m_mutex);
841 SCP_DEBUG(()) <<
"Invalidating " << m_ranges.size() <<
" ranges";
842 auto rit = m_ranges.begin();
843 while (
rit != m_ranges.end()) {
844 invalidate_single_range(
rit->first,
rit->second);
845 rit = m_ranges.erase(
rit);
858 if (m_finished)
return;
861 std::lock_guard<std::mutex>
lock(m_mutex);
863 for (
auto m : m_mmio_mrs) {
865 auto mr_end =
m.first +
m.second->get_size() - 1;
873 if (
it !=
m.second->m_mapped_te.begin()) {
874 auto prev = std::prev(
it);
877 m.second->iommu_unmap(&(
prev->second));
878 m.second->m_mapped_te.erase(
prev);
879 SCP_TRACE(())(
"Region removed 0x{:x} (mask 0x{:x})",
prev->first,
it->second.addr_mask);
886 m.second->iommu_unmap(&(
it->second));
887 it =
m.second->m_mapped_te.erase(
it);
888 SCP_TRACE(())(
"Region removed 0x{:x} (mask 0x{:x})",
it->first,
it->second.addr_mask);
894 SCP_DEBUG(())(
"Region(s) removed in range [0x{:x} - 0x{:x}] from mr [0x{:x} - 0x{:x}]",
start_range,
901 m_initiator.initiator_async_run([&]() { invalidate_ranges_safe_cb(); });
906 std::lock_guard<std::mutex>
lock(m_mutex);
908 for (
auto m : m_mmio_mrs) {
909 m.second->m_mapped_te.clear();
910 auto it = m_dmi_aliases.begin();
911 while (
it != m_dmi_aliases.end()) {
912 DmiRegionAlias::Ptr r =
it->second;
913 it = remove_alias(
it);