Convert drivers to use Platform::Session::dma_addr

This patch eliminates several calls of 'Dataspace::phys_addr'.

Issue #2243
This commit is contained in:
Norman Feske 2022-02-02 15:05:28 +01:00
parent 90a6f55f88
commit 51479e6be0
29 changed files with 192 additions and 98 deletions

View File

@ -84,7 +84,7 @@ class Pci_driver : public Bsd::Bus_driver
try {
Ram_dataspace_capability cap = _drv._alloc_dma_memory(BACKING_STORE_SIZE);
mapped_base = (addr_t)env.rm().attach(cap);
base = Dataspace_client(cap).phys_addr();
base = _drv._dma_addr(cap);
Allocator_avl::add_range(mapped_base, BACKING_STORE_SIZE);
} catch (...) {
@ -146,6 +146,14 @@ class Pci_driver : public Bsd::Bus_driver
});
}
/**
* Get physical address for DMA dataspace
*/
Genode::addr_t _dma_addr(Genode::Ram_dataspace_capability ds_cap)
{
return _pci.dma_addr(ds_cap);
}
public:
Pci_driver(Genode::Env &env, Genode::Allocator &alloc)

View File

@ -254,7 +254,7 @@ struct Pci_driver
});
_region.mapped_base = _rm.attach(ram_cap);
_region.base = Dataspace_client(ram_cap).phys_addr();
_region.base = _pci.dma_addr(ram_cap);
return _region.mapped_base;
} catch (...) {

View File

@ -16,7 +16,7 @@
<service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<start name="platform_drv" caps="150" managing_system="yes">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>

View File

@ -16,7 +16,7 @@
<service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<start name="platform_drv" caps="150" managing_system="yes">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>

View File

@ -14,7 +14,7 @@
<default caps="100"/>
<start name="platform_drv" caps="150">
<start name="platform_drv" caps="150" managing_system="yes">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>

View File

@ -144,7 +144,7 @@ append config {
if { [have_spec x86] } { append_platform_drv_config
} else {
append config "<start name=\"[platform_drv_binary_non_x86]\">"
append config "<start name=\"[platform_drv_binary_non_x86]\" managing_system=\"yes\">"
append config {
<resource name="RAM" quantum="1M"/>
<provides><service name="Platform"/></provides>

View File

@ -1476,3 +1476,38 @@ int try_module_get(struct module *mod)
}
}
#include <base/ram_allocator.h>
#include <legacy/lx_kit/backend_alloc.h>
#include <legacy/lx_kit/env.h>
/****************************
** lx_kit/backend_alloc.h **
****************************/
void backend_alloc_init(Genode::Env&, Genode::Ram_allocator&,
Genode::Allocator&)
{
/* intentionally left blank */
}
Genode::Ram_dataspace_capability Lx::backend_alloc(addr_t size, Cache cache)
{
return platform_connection().alloc_dma_buffer(size, cache);
}
void Lx::backend_free(Genode::Ram_dataspace_capability cap)
{
return platform_connection().free_dma_buffer(cap);
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability cap)
{
return platform_connection().dma_addr(cap);
}

View File

@ -1,39 +0,0 @@
/*
* \brief Platform driver relevant lx_kit backend functions
* \author Stefan Kalkowski
* \date 2017-11-01
*
* Taken from the USB driver.
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/ram_allocator.h>
#include <legacy/lx_kit/backend_alloc.h>
#include <legacy/lx_kit/env.h>
/****************************
** lx_kit/backend_alloc.h **
****************************/
void backend_alloc_init(Genode::Env&, Genode::Ram_allocator&,
Genode::Allocator&)
{
/* intentionally left blank */
}
Genode::Ram_dataspace_capability
Lx::backend_alloc(Genode::addr_t size, Genode::Cache cache) {
return Lx_kit::env().env().ram().alloc(size, cache); }
void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
return Lx_kit::env().env().ram().free(cap); }

View File

@ -1,6 +1,6 @@
TARGET = fec_nic_drv
LIBS = base lx_kit_setjmp fec_nic_include nic_driver
SRC_CC += main.cc platform.cc lx_emul.cc uplink_client.cc
SRC_CC += main.cc lx_emul.cc uplink_client.cc
SRC_CC += linux_network_session_base.cc
SRC_C += dummy.c lxc.c
INC_DIR += $(PRG_DIR)/../..

View File

@ -202,6 +202,12 @@ void Lx::backend_free(Ram_dataspace_capability cap)
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability cap)
{
return resource_env().platform.dma_addr(cap);
}
/**********************
** asm-generic/io.h **
**********************/

View File

@ -225,6 +225,12 @@ int usb_register_driver(struct usb_driver * driver, struct module *, const char
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability)
{
return 0;
}
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv)
{
usb_device *udev = interface_to_usbdev(iface);

View File

@ -203,6 +203,12 @@ Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size,
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability)
{
return 0;
}
int usb_register_driver(struct usb_driver * driver, struct module *, const char *)
{
INIT_LIST_HEAD(&driver->dynids.list);

View File

@ -30,8 +30,8 @@ struct page *alloc_pages(gfp_t const gfp_mask, unsigned int order)
Cache const cache = (gfp_mask & dma_mask) ? Genode::UNCACHED
: Genode::CACHED;
Genode::Ram_dataspace_capability ds_cap = Lx::backend_alloc(size, cache);
page->addr = Lx_kit::env().rm().attach(ds_cap);
page->paddr = Genode::Dataspace_client(ds_cap).phys_addr();
page->addr = Lx_kit::env().rm().attach(ds_cap);
page->paddr = Lx::backend_dma_addr(ds_cap);
if (!page->addr) {
Genode::error("alloc_pages: ", size, " failed");

View File

@ -26,7 +26,10 @@ namespace Lx {
using namespace Genode;
Ram_dataspace_capability backend_alloc(addr_t size, Cache);
void backend_free(Ram_dataspace_capability cap);
addr_t backend_dma_addr(Ram_dataspace_capability);
}
#endif /* _LX_KIT__BACKEND_ALLOC_H_ */

View File

@ -67,7 +67,7 @@ class Lx_kit::Slab_backend_alloc : public Lx::Slab_backend_alloc,
Region_map_client::attach_at(_ds_cap[_index], _index * V_BLOCK_SIZE, P_BLOCK_SIZE, 0);
/* lookup phys. address */
_ds_phys[_index] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr();
_ds_phys[_index] = Lx::backend_dma_addr(_ds_cap[_index]);
} catch (...) { return false; }
/* return base + offset in VM area */

View File

@ -43,6 +43,8 @@ struct Lx_kit::Memory_object_base : Genode::Object_pool<Memory_object_base>::Ent
virtual void free() = 0;
virtual Genode::addr_t dma_addr() const { return 0; }
Genode::Ram_dataspace_capability ram_cap()
{
using namespace Genode;
@ -67,11 +69,15 @@ struct Lx_kit::Dma_object : Memory_object_base
{
Platform::Connection &_pci;
Genode::addr_t const _dma_addr = _pci.dma_addr(ram_cap());
Dma_object(Platform::Connection &pci,
Genode::Ram_dataspace_capability cap)
: Memory_object_base(cap), _pci(pci) {}
: Memory_object_base(cap), _pci(pci) { }
void free() { _pci.free_dma_buffer(ram_cap()); }
Genode::addr_t dma_addr() const override { return _dma_addr; }
};
@ -159,3 +165,17 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap)
});
destroy(_global_md_alloc, object);
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability cap)
{
using namespace Genode;
using namespace Lx_kit;
addr_t result = 0;
memory_pool.apply(cap, [&] (Dma_object *obj_ptr) {
if (obj_ptr)
result = obj_ptr->dma_addr(); });
return result;
}

View File

@ -102,6 +102,12 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap)
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability)
{
return 0;
}
/*************************************
** Memory allocation, linux/slab.h **
*************************************/

View File

@ -67,6 +67,7 @@ class Ahci::Platform
*/
Ram_dataspace_capability alloc_dma_buffer(size_t size);
void free_dma_buffer(Ram_dataspace_capability ds);
addr_t dma_addr(Ram_dataspace_capability);
};
/**
@ -498,6 +499,8 @@ struct Ahci::Port : private Port_base
Ram_dataspace_capability cmd_ds { };
Ram_dataspace_capability device_info_ds { };
addr_t device_info_dma_addr = 0;
addr_t cmd_list = 0;
addr_t fis_base = 0;
addr_t cmd_table = 0;
@ -846,7 +849,7 @@ struct Ahci::Port : private Port_base
device_ds = hba.alloc_dma_buffer(0x1000);
/* command list 1K */
addr_t phys = Dataspace_client(device_ds).phys_addr();
addr_t phys = hba.dma_addr(device_ds);
cmd_list = (addr_t)rm.attach(device_ds);
command_list_base(phys);
@ -865,7 +868,7 @@ struct Ahci::Port : private Port_base
size_t cmd_size = align_addr(cmd_slots * Command_table::size(), 12);
cmd_ds = hba.alloc_dma_buffer(cmd_size);
cmd_table = (addr_t)rm.attach(cmd_ds);
phys = (addr_t)Dataspace_client(cmd_ds).phys_addr();
phys = hba.dma_addr(cmd_ds);
/* set command table addresses in command list */
for (unsigned i = 0; i < cmd_slots; i++) {
@ -874,8 +877,9 @@ struct Ahci::Port : private Port_base
}
/* dataspace for device info */
device_info_ds = hba.alloc_dma_buffer(0x1000);
device_info = rm.attach(device_info_ds);
device_info_ds = hba.alloc_dma_buffer(0x1000);
device_info_dma_addr = hba.dma_addr(device_info_ds);
device_info = rm.attach(device_info_ds);
}
addr_t command_table_addr(unsigned slot)
@ -918,7 +922,7 @@ struct Ahci::Port : private Port_base
if (dma_base) return Ram_dataspace_capability();
Ram_dataspace_capability dma = hba.alloc_dma_buffer(size);
dma_base = Dataspace_client(dma).phys_addr();
dma_base = hba.dma_addr(dma);
return dma;
}

View File

@ -222,9 +222,8 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
unsigned init(Port &port) override
{
/* identify device */
addr_t phys = Dataspace_client(port.device_info_ds).phys_addr();
Command_table table(port.command_table_addr(0), phys, 0x1000);
Command_table table(port.command_table_addr(0),
port.device_info_dma_addr, 0x1000);
table.fis.identify_device();
port.execute(0);

View File

@ -41,9 +41,8 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
void _read_sense(Port &port)
{
addr_t phys = Dataspace_client(port.device_info_ds).phys_addr();
Command_table table(port.command_table_addr(0), phys, 0x1000);
Command_table table(port.command_table_addr(0),
port.device_info_dma_addr, 0x1000);
table.fis.atapi();
table.atapi_cmd.read_sense();
@ -61,9 +60,8 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
void _read_capacity(Port &port)
{
addr_t phys = Dataspace_client(port.device_info_ds).phys_addr();
Command_table table(port.command_table_addr(0), phys, 0x1000);
Command_table table(port.command_table_addr(0),
port.device_info_dma_addr, 0x1000);
table.fis.atapi();
table.fis.byte_count(~0);

View File

@ -85,3 +85,9 @@ void Ahci::Platform::free_dma_buffer(Genode::Ram_dataspace_capability ds)
{
_data.pci.free_dma_buffer(ds);
}
Genode::addr_t Ahci::Platform::dma_addr(Genode::Ram_dataspace_capability ds)
{
return _data.pci.dma_addr(ds);
}

View File

@ -112,6 +112,11 @@ struct Igd::Device
_pci.free_dma_buffer(cap);
}
addr_t dma_addr(Ram_dataspace_capability ds_cap) override
{
return _pci.dma_addr(ds_cap);
}
} _pci_backend_alloc { _resources.platform() };
@ -262,11 +267,11 @@ struct Igd::Device
Genode::Registry<Genode::Registered<Ggtt_mmio_mapping>> _ggtt_mmio_mapping_registry { };
Ggtt_mmio_mapping const &map_dataspace_ggtt(Genode::Allocator &alloc,
Genode::Dataspace_capability cap,
Genode::Ram_dataspace_capability cap,
Ggtt::Offset offset)
{
Genode::Dataspace_client client(cap);
addr_t const phys_addr = client.phys_addr();
addr_t const phys_addr = _pci_backend_alloc.dma_addr(cap);
size_t const size = client.size();
/*
@ -1303,12 +1308,25 @@ struct Igd::Device
*
* \throw Out_of_memory
*/
Genode::Dataspace_capability alloc_buffer(Allocator &,
size_t const size)
Genode::Ram_dataspace_capability alloc_buffer(Allocator &,
size_t const size)
{
return _pci_backend_alloc.alloc(size);
}
/**
* Get physical address for DMA buffer
*
* \param ds_cap ram dataspace capability
*
* \return physical DMA address
*/
Genode::addr_t dma_addr(Genode::Ram_dataspace_capability ds_cap)
{
return _pci_backend_alloc.dma_addr(ds_cap);
}
/**
* Free DMA buffer
*
@ -1335,7 +1353,8 @@ struct Igd::Device
* \throw Could_not_map_buffer
*/
Ggtt::Mapping const &map_buffer(Genode::Allocator &guard,
Genode::Dataspace_capability cap, bool aperture)
Genode::Ram_dataspace_capability cap,
bool aperture)
{
if (aperture == false) {
error("GGTT mapping outside aperture");
@ -1569,8 +1588,8 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
*/
struct Buffer : Rpc_object<Gpu::Buffer>
{
Dataspace_capability ds_cap;
Session_capability owner_cap;
Ram_dataspace_capability ds_cap;
Session_capability owner_cap;
enum { INVALID_FENCE = 0xff };
Genode::uint32_t fenced { INVALID_FENCE };
@ -1580,11 +1599,13 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
addr_t phys_addr { 0 };
size_t size { 0 };
Buffer(Dataspace_capability ds_cap, Session_capability owner_cap)
: ds_cap { ds_cap }, owner_cap { owner_cap }
Buffer(Ram_dataspace_capability ds_cap, Genode::addr_t phys_addr,
Session_capability owner_cap)
:
ds_cap { ds_cap }, owner_cap { owner_cap },
phys_addr { phys_addr }
{
Dataspace_client buf(ds_cap);
phys_addr = buf.phys_addr();
size = buf.size();
}
@ -1809,10 +1830,11 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
Resource_guard::Reservation reserve =
_resource_guard.alloc_buffer(Ram_quota { size });
Genode::Dataspace_capability ds_cap =
Genode::Ram_dataspace_capability ds_cap =
_device.alloc_buffer(_heap, size);
Genode::addr_t phys_addr = _device.dma_addr(ds_cap);
Buffer *buffer = new (&_heap) Buffer(ds_cap, _session_cap);
Buffer *buffer = new (&_heap) Buffer(ds_cap, phys_addr, _session_cap);
_env.ep().manage(*buffer);
try {
new (&_heap) Buffer_local(buffer->cap(), size, _buffer_space, id);

View File

@ -178,25 +178,25 @@ namespace Genode
{
/* XXX addr PAT helper instead of hardcoding */
page.ds = _backend.alloc(PAGE_SIZE);
page.addr = Genode::Dataspace_client(page.ds).phys_addr();
page.addr = _backend.dma_addr(page.ds);
page.addr |= 1;
page.addr |= 1 << 1;
page.next = nullptr;
pt.ds = _backend.alloc(PAGE_SIZE);
pt.addr = Genode::Dataspace_client(pt.ds).phys_addr();
pt.addr = _backend.dma_addr(pt.ds);
pt.addr |= 1;
pt.addr |= 1 << 1;
pt.next = &page;
pd.ds = _backend.alloc(PAGE_SIZE);
pd.addr = Genode::Dataspace_client(pd.ds).phys_addr();
pd.addr = _backend.dma_addr(pd.ds);
pd.addr |= 1;
pd.addr |= 1 << 1;
pd.next = &pt;
pdp.ds = _backend.alloc(PAGE_SIZE);
pdp.addr = Genode::Dataspace_client(pdp.ds).phys_addr();
pdp.addr = _backend.dma_addr(pdp.ds);
pdp.addr |= 1;
pdp.addr |= 1 << 1;
pdp.next = &pd;

View File

@ -80,16 +80,17 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator
Alloc_error alloc_error = Alloc_error::DENIED;
try {
void * const ptr = _rm.attach(ds);
void * const va = _rm.attach(ds);
void * const pa = (void*)_backend.dma_addr(ds);
if (_map.add(ds, ptr) == true) {
_range.add_range((Genode::addr_t)ptr, alloc_size);
if (_map.add(ds, pa, va, alloc_size) == true) {
_range.add_range((Genode::addr_t)va, alloc_size);
result = _range.alloc_aligned(size, 12);
return result;
}
/* _map.add failed, roll back _rm.attach */
_rm.detach(ptr);
_rm.detach(va);
}
catch (Genode::Out_of_ram) { alloc_error = Alloc_error::OUT_OF_RAM; }
catch (Genode::Out_of_caps) { alloc_error = Alloc_error::OUT_OF_CAPS; }

View File

@ -75,7 +75,7 @@ class Igd::Resources : Genode::Noncopyable
return _platform.alloc_dma_buffer(PAGE_SIZE, Genode::UNCACHED); }) };
addr_t _scratch_page {
Genode::Dataspace_client(_scratch_page_ds).phys_addr() };
_platform.dma_addr(_scratch_page_ds) };
/* aperture */
enum {

View File

@ -31,6 +31,7 @@ namespace Utils {
{
virtual Ram alloc(Genode::size_t) = 0;
virtual void free(Ram) = 0;
virtual Genode::addr_t dma_addr(Ram) = 0;
};
template <unsigned int ELEMENTS> class Address_map;
@ -58,12 +59,12 @@ class Utils::Address_map
Element() { }
Element(Ram ds_cap, void *va)
Element(Ram ds_cap, void *pa, void *va, size_t size)
:
ds_cap(ds_cap),
va((addr_t)va),
pa(Genode::Dataspace_client(ds_cap).phys_addr()),
size(Genode::Dataspace_client(ds_cap).size())
pa((addr_t)pa),
size(size)
{ }
Element(Element const &other)
@ -105,12 +106,12 @@ class Utils::Address_map
}
}
bool add(Ram ds_cap, void *va)
bool add(Ram ds_cap, void *pa, void *va, size_t size)
{
for (uint32_t i = 0; i < ELEMENTS; i++) {
if (_map[i].valid()) { continue; }
_map[i] = Element(ds_cap, va);
_map[i] = Element(ds_cap, pa, va, size);
return true;
}
return false;

View File

@ -783,7 +783,7 @@ struct Nvme::Controller : public Genode::Attached_dataspace,
{
size_t const size = num * len;
q.ds = _dma_alloc.alloc(size);
q.pa = Dataspace_client(q.ds).phys_addr();
q.pa = _dma_alloc.dma_addr(q.ds);
q.va = (addr_t)_env.rm().attach(q.ds);
q.max_entries = num;
}
@ -877,7 +877,8 @@ struct Nvme::Controller : public Genode::Attached_dataspace,
if (!_nvme_nslist.va) {
Ram_dataspace_capability ds = _dma_alloc.alloc(IDENTIFY_LEN);
_nvme_nslist.va = (addr_t)_env.rm().attach(ds);
_nvme_nslist.pa = Dataspace_client(ds).phys_addr();
_nvme_nslist.pa = _dma_alloc.dma_addr(ds);
}
uint32_t *nslist = (uint32_t*)_nvme_nslist.va;
@ -928,7 +929,7 @@ struct Nvme::Controller : public Genode::Attached_dataspace,
if (!_nvme_query_ns[id].va) {
Ram_dataspace_capability ds = _dma_alloc.alloc(IDENTIFY_LEN);
_nvme_query_ns[id].va = (addr_t)_env.rm().attach(ds);
_nvme_query_ns[id].pa = Dataspace_client(ds).phys_addr();
_nvme_query_ns[id].pa = _dma_alloc.dma_addr(ds);
}
Sqe_identify b(_admin_command(Opcode::IDENTIFY, ns[id], QUERYNS_CID));
@ -961,7 +962,7 @@ struct Nvme::Controller : public Genode::Attached_dataspace,
if (!_nvme_identify.va) {
Ram_dataspace_capability ds = _dma_alloc.alloc(IDENTIFY_LEN);
_nvme_identify.va = (addr_t)_env.rm().attach(ds);
_nvme_identify.pa = Dataspace_client(ds).phys_addr();
_nvme_identify.pa = _dma_alloc.dma_addr(ds);
}
Sqe_identify b(_admin_command(Opcode::IDENTIFY, 0, IDENTIFY_CID));
@ -1557,7 +1558,7 @@ class Nvme::Driver : Genode::Noncopyable
error("could not allocate DMA backing store");
throw Nvme::Controller::Initialization_failed();
}
addr_t const phys_addr = Genode::Dataspace_client(ds).phys_addr();
addr_t const phys_addr = _nvme_pci->dma_addr(ds);
addr_t const virt_addr = (addr_t)_env.rm().attach(ds);
_prp_list_helper.construct(ds, phys_addr, virt_addr);
@ -1620,7 +1621,7 @@ class Nvme::Driver : Genode::Noncopyable
Genode::Ram_dataspace_capability dma_alloc(size_t size)
{
Genode::Ram_dataspace_capability cap = _nvme_pci->alloc(size);
_dma_base = Dataspace_client(cap).phys_addr();
_dma_base = _nvme_pci->dma_addr(cap);
return cap;
}

View File

@ -139,6 +139,16 @@ struct Nvme::Pci : Platform::Connection,
{
Pci::Connection::free_dma_buffer(cap);
}
/**
* Return bus address of DMA buffer
*
* \param cap RAM dataspace capability
*/
addr_t dma_addr(Ram_dataspace_capability cap) override
{
return Pci::Connection::dma_addr(cap);
}
};
#endif /* _NVME_PCI_H_ */

View File

@ -26,8 +26,9 @@ namespace Util {
*/
struct Dma_allocator : Genode::Interface
{
virtual Genode::Ram_dataspace_capability alloc(size_t) = 0;
virtual void free(Genode::Ram_dataspace_capability) = 0;
virtual Ram_dataspace_capability alloc(size_t) = 0;
virtual void free(Ram_dataspace_capability) = 0;
virtual addr_t dma_addr(Ram_dataspace_capability) = 0;
};
/**