x86/platform_drv: add Platform::Session::dma_addr

This patch adds the designated alternative to Dataspace::phys_addr to
the platform-session interface. Under the hood, the platform driver
still calls Dataspace::phys_addr but it should eventuelly become the
only caller before we can abolish this function.

Issue #2243
This commit is contained in:
Norman Feske 2021-04-07 18:11:26 +02:00
parent 97a9ad114c
commit 3ed8df9089
6 changed files with 63 additions and 24 deletions

View File

@ -44,6 +44,9 @@ struct Platform::Client : public Genode::Rpc_client<Session>
void free_dma_buffer(Genode::Ram_dataspace_capability cap) override {
call<Rpc_free_dma_buffer>(cap); }
Genode::addr_t dma_addr(Genode::Ram_dataspace_capability cap) override {
return call<Rpc_dma_addr>(cap); }
Device_capability device(String const &device) override {
return call<Rpc_device>(device); }
};

View File

@ -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_ */

View File

@ -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");

View File

@ -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);
};

View File

@ -71,9 +71,15 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
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<Platform::Device>,
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());

View File

@ -120,6 +120,8 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
return Genode::Io_mem_dataspace_capability();
}
addr_t start() const { return _start; }
void add(Bdf * bdf) { _bdf_list.insert(bdf); }
static Genode::List<Rmrr> *list()
@ -208,6 +210,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
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<Session>
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>
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<Session>
_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<Session>
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<Session>
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<Session>
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<Session>
_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<Session_component>
Genode::Attached_rom_dataspace &_config;
Genode::Constructible<Genode::Attached_io_mem_dataspace> _pci_confspace { };
Genode::addr_t _pci_confspace_base = 0;
Genode::Constructible<Genode::Expanding_reporter> _pci_reporter { };
@ -913,6 +937,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
log("ECAM/MMCONF range ", bdf_first, "-", bdf_last, " - addr ",
Hex_range<addr_t>(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<Session_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<Session_component>
Genode::Registered<Session_component>(_sessions, _env,
_config,
*_pci_confspace,
_pci_confspace_base,
*_buses, _heap,
_delayer,
_devices_bars, args,