diff --git a/repos/os/include/spec/x86/platform_session/client.h b/repos/os/include/spec/x86/platform_session/client.h index 952e78c4fd..bcab4ae48a 100644 --- a/repos/os/include/spec/x86/platform_session/client.h +++ b/repos/os/include/spec/x86/platform_session/client.h @@ -44,6 +44,9 @@ struct Platform::Client : public Genode::Rpc_client void free_dma_buffer(Genode::Ram_dataspace_capability cap) override { call(cap); } + Genode::addr_t dma_addr(Genode::Ram_dataspace_capability cap) override { + return call(cap); } + Device_capability device(String const &device) override { return call(device); } }; diff --git a/repos/os/include/spec/x86/platform_session/platform_session.h b/repos/os/include/spec/x86/platform_session/platform_session.h index 02b9718259..6a8bf26fad 100644 --- a/repos/os/include/spec/x86/platform_session/platform_session.h +++ b/repos/os/include/spec/x86/platform_session/platform_session.h @@ -68,13 +68,13 @@ struct Platform::Session : Genode::Session typedef Genode::Rpc_in_buffer<8> String; /** - * Provide non-PCI device known by unique name. + * Provide non-PCI device known by unique name */ virtual Device_capability device(String const &string) = 0; /** - * Allocate memory suitable for DMA. - */ + * Allocate memory suitable for DMA + */ virtual Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t) = 0; /** @@ -82,6 +82,10 @@ struct Platform::Session : Genode::Session */ virtual void free_dma_buffer(Genode::Ram_dataspace_capability) = 0; + /** + * Return the bus address of the previously allocated DMA memory + */ + virtual Genode::addr_t dma_addr(Genode::Ram_dataspace_capability) = 0; /********************* ** RPC declaration ** @@ -100,13 +104,15 @@ struct Platform::Session : Genode::Session Genode::size_t); GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, Genode::Ram_dataspace_capability); + GENODE_RPC(Rpc_dma_addr, Genode::addr_t, dma_addr, + Genode::Ram_dataspace_capability); GENODE_RPC_THROW(Rpc_device, Device_capability, device, GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), String const &); GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device, Rpc_release_device, Rpc_alloc_dma_buffer, - Rpc_free_dma_buffer, Rpc_device); + Rpc_free_dma_buffer, Rpc_dma_addr, Rpc_device); }; #endif /* _INCLUDE__SPEC__X86__PLATFORM_SESSION__PLATFORM_SESSION_H_ */ diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd.cc b/repos/os/src/drivers/platform/spec/x86/device_pd.cc index 0a12f787c7..12e466ad67 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd.cc +++ b/repos/os/src/drivers/platform/spec/x86/device_pd.cc @@ -20,19 +20,19 @@ #include "device_pd.h" -void Platform::Device_pd::attach_dma_mem(Genode::Dataspace_capability ds_cap) +void Platform::Device_pd::attach_dma_mem(Genode::Dataspace_capability ds_cap, + Genode::addr_t const dma_addr) { using namespace Genode; Dataspace_client ds_client(ds_cap); - addr_t const phys = ds_client.phys_addr(); size_t const size = ds_client.size(); addr_t page = ~0UL; try { - page = _address_space.attach_at(ds_cap, phys); + page = _address_space.attach_at(ds_cap, dma_addr); /* trigger eager mapping of memory */ _pd.map(page, size); } @@ -42,18 +42,19 @@ void Platform::Device_pd::attach_dma_mem(Genode::Dataspace_capability ds_cap) /* * DMA memory already attached before. */ - page = phys; + page = dma_addr; } catch (...) { error(_label, ": attach_at or map failed"); } /* sanity check */ - if ((page == ~0UL) || (page != phys)) { + if ((page == ~0UL) || (page != dma_addr)) { if (page != ~0UL) _address_space.detach(page); Genode::error(_label, ": attachment of DMA memory @ ", - Genode::Hex(phys), "+", Genode::Hex(size), " failed page=", Genode::Hex(page)); + Genode::Hex(dma_addr), "+", Genode::Hex(size), " " + "failed page=", Genode::Hex(page)); return; } } @@ -93,7 +94,6 @@ void Platform::Device_pd::assign_pci(Genode::Io_mem_dataspace_capability const i /* try to assign pci device to this protection domain */ if (!_pd.assign_pci(page, rid)) Genode::error(_label, ": assignment of PCI device ", Rid(rid), " failed ", - "phys=", Genode::Hex(ds_client.phys_addr() + offset), " " "virt=", Genode::Hex(page)); else Genode::log(_label,": assignment of PCI device ", Rid(rid), " succeeded"); diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd.h b/repos/os/src/drivers/platform/spec/x86/device_pd.h index ab378dfe83..f2aba6ff3a 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd.h +++ b/repos/os/src/drivers/platform/spec/x86/device_pd.h @@ -110,7 +110,7 @@ class Platform::Device_pd _pd.ref_account(env.pd_session_cap()); } - void attach_dma_mem(Genode::Dataspace_capability); + void attach_dma_mem(Genode::Dataspace_capability, Genode::addr_t dma_addr); void assign_pci(Genode::Io_mem_dataspace_capability const, Genode::addr_t const, Genode::uint16_t const); }; diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h index 925ce0c324..cf56b68593 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h @@ -71,9 +71,15 @@ class Platform::Device_component : public Genode::Rpc_object, public: - Io_mem (Genode::Env &env, Genode::addr_t base, - Genode::size_t size, bool wc) - : Genode::Io_mem_connection(env, base, size, wc) { } + Genode::addr_t const base; + Genode::size_t const size; + + Io_mem(Genode::Env &env, Genode::addr_t base, + Genode::size_t size, bool wc) + : + Genode::Io_mem_connection(env, base, size, wc), + base(base), size(size) + { } }; enum { @@ -309,13 +315,11 @@ class Platform::Device_component : public Genode::Rpc_object, for (Io_mem * io_mem = _io_mem[i].first(); io_mem; io_mem = io_mem->next()) { - Dataspace_client ds_client(io_mem->dataspace()); - - if (!(ds_client.phys_addr() <= msix_table_phys && - msix_table_phys + msix_table_size <= ds_client.phys_addr() + ds_client.size())) + if (!(io_mem->base <= msix_table_phys && + msix_table_phys + msix_table_size <= io_mem->base + io_mem->size)) continue; - Genode::size_t const offset = msix_table_phys - ds_client.phys_addr(); + Genode::size_t const offset = msix_table_phys - io_mem->base; Attached_dataspace mem_io(_env.rm(), io_mem->dataspace()); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index b17657bb50..a46480d8c6 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -120,6 +120,8 @@ class Platform::Rmrr : public Genode::List::Element return Genode::Io_mem_dataspace_capability(); } + addr_t start() const { return _start; } + void add(Bdf * bdf) { _bdf_list.insert(bdf); } static Genode::List *list() @@ -208,6 +210,7 @@ class Platform::Session_component : public Genode::Rpc_object Genode::Env &_env; Genode::Attached_rom_dataspace &_config; Genode::Attached_io_mem_dataspace &_pciconf; + Genode::addr_t const _pciconf_base; Genode::Ram_quota_guard _ram_guard; Genode::Cap_quota_guard _cap_guard; Genode::Constrained_ram_allocator _env_ram { @@ -230,6 +233,15 @@ class Platform::Session_component : public Genode::Rpc_object void _insert(Ram_capability cap) { _ram_caps.insert(new (_md_alloc) Platform::Ram_dataspace(cap)); } + bool _owned(Ram_capability cap) + { + for (Ram_dataspace *ds = _ram_caps.first(); ds; ds = ds->next()) + if (ds->match(cap)) + return true; + + return false; + } + bool _remove(Ram_capability cap) { for (Platform::Ram_dataspace *ds = _ram_caps.first(); ds; @@ -469,6 +481,7 @@ class Platform::Session_component : public Genode::Rpc_object Session_component(Genode::Env &env, Genode::Attached_rom_dataspace &config, Genode::Attached_io_mem_dataspace &pciconf, + Genode::addr_t pciconf_base, Platform::Pci_buses &buses, Genode::Heap &global_heap, Pci::Config::Delayer &delayer, @@ -479,6 +492,7 @@ class Platform::Session_component : public Genode::Rpc_object _env(env), _config(config), _pciconf(pciconf), + _pciconf_base(pciconf_base), _ram_guard(Genode::ram_quota_from_args(args)), _cap_guard(Genode::cap_quota_from_args(args)), _md_alloc(_env_ram, env.rm()), @@ -792,7 +806,7 @@ class Platform::Session_component : public Genode::Rpc_object return; try { - addr_t const base_ecam = Dataspace_client(_pciconf.cap()).phys_addr(); + addr_t const base_ecam = _pciconf_base; addr_t const base_offset = 0x1000UL * device->device_config().bdf().value(); if (base_ecam + base_offset != device->config_space()) @@ -801,7 +815,7 @@ class Platform::Session_component : public Genode::Rpc_object for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->device_config()); if (rmrr_cap.valid()) - _device_pd.attach_dma_mem(rmrr_cap); + _device_pd.attach_dma_mem(rmrr_cap, r->start()); } _device_pd.assign_pci(_pciconf.cap(), base_offset, @@ -819,12 +833,13 @@ class Platform::Session_component : public Genode::Rpc_object Ram_capability alloc_dma_buffer(Genode::size_t const size) override { Ram_capability ram_cap = _env_ram.alloc(size, Genode::UNCACHED); + addr_t const dma_addr = Dataspace_client(ram_cap).phys_addr(); if (!ram_cap.valid()) return ram_cap; try { - _device_pd.attach_dma_mem(ram_cap); + _device_pd.attach_dma_mem(ram_cap, dma_addr); _insert(ram_cap); } catch (Out_of_ram) { _env_ram.free(ram_cap); @@ -845,6 +860,14 @@ class Platform::Session_component : public Genode::Rpc_object _env_ram.free(ram_cap); } + Genode::addr_t dma_addr(Ram_capability ram_cap) override + { + if (!ram_cap.valid() || !_owned(ram_cap)) + return 0; + + return Dataspace_client(ram_cap).phys_addr(); + } + Device_capability device(String const &name) override; }; @@ -857,6 +880,7 @@ class Platform::Root : public Genode::Root_component Genode::Attached_rom_dataspace &_config; Genode::Constructible _pci_confspace { }; + Genode::addr_t _pci_confspace_base = 0; Genode::Constructible _pci_reporter { }; @@ -913,6 +937,7 @@ class Platform::Root : public Genode::Root_component log("ECAM/MMCONF range ", bdf_first, "-", bdf_last, " - addr ", Hex_range(base, memory_size)); + _pci_confspace_base = base; _pci_confspace.construct(env, base, memory_size); }); @@ -1020,7 +1045,7 @@ class Platform::Root : public Genode::Root_component void _construct_buses() { Genode::Dataspace_client ds_pci_mmio(_pci_confspace->cap()); - uint64_t const phys_addr = ds_pci_mmio.phys_addr(); + uint64_t const phys_addr = _pci_confspace_base; uint64_t const phys_size = ds_pci_mmio.size(); uint64_t mmio_size = 0x10000000UL; /* max MMCONF memory */ @@ -1065,6 +1090,7 @@ class Platform::Root : public Genode::Root_component Genode::Registered(_sessions, _env, _config, *_pci_confspace, + _pci_confspace_base, *_buses, _heap, _delayer, _devices_bars, args,