platform_drv: replace nova specific device_pd

by using generic Pd_session::map instead for eager memory mappings of DMA
memory.

Issue #2209
This commit is contained in:
Alexander Boettcher 2017-08-01 19:05:56 +02:00 committed by Christian Helmuth
parent fe4bdde687
commit 69e71147ef
9 changed files with 199 additions and 532 deletions

View File

@ -15,16 +15,6 @@ include/spec/%/trace/timestamp.h:
cp $(GENODE_DIR)/repos/os/$@ $@ cp $(GENODE_DIR)/repos/os/$@ $@
DEVICE_PD_SRC := src/drivers/platform/spec/x86/pci_device_pd_ipc.h \
src/drivers/platform/spec/x86/device_pd \
include/os/static_root.h
content: $(DEVICE_PD_SRC)
$(DEVICE_PD_SRC):
mkdir -p $(dir $@)
cp -r $(GENODE_DIR)/repos/os/$@ $@
content: README content: README
README: README:
cp $(REP_DIR)/recipes/src/base-nova/README $@ cp $(REP_DIR)/recipes/src/base-nova/README $@

View File

@ -54,7 +54,6 @@ proc platform_drv_build_components {} {
lappend_if [have_platform_drv] drv_build_components drivers/platform lappend_if [have_platform_drv] drv_build_components drivers/platform
lappend_if [have_spec acpi] drv_build_components drivers/acpi lappend_if [have_spec acpi] drv_build_components drivers/acpi
lappend_if [have_spec acpi] drv_build_components server/report_rom lappend_if [have_spec acpi] drv_build_components server/report_rom
lappend_if [have_spec nova] drv_build_components drivers/platform/spec/x86/device_pd
return $drv_build_components return $drv_build_components
} }
@ -69,7 +68,6 @@ proc platform_drv_boot_modules {} {
lappend_if [have_platform_drv] drv_boot_modules platform_drv lappend_if [have_platform_drv] drv_boot_modules platform_drv
lappend_if [have_spec acpi] drv_boot_modules acpi_drv lappend_if [have_spec acpi] drv_boot_modules acpi_drv
lappend_if [have_spec acpi] drv_boot_modules report_rom lappend_if [have_spec acpi] drv_boot_modules report_rom
lappend_if [have_spec nova] drv_boot_modules device_pd
lappend_if [have_spec muen] drv_boot_modules acpi lappend_if [have_spec muen] drv_boot_modules acpi
return $drv_boot_modules return $drv_boot_modules
} }

View File

@ -0,0 +1,103 @@
/*
* \brief Pci device protection domain service for platform driver
* \author Alexander Boettcher
* \date 2013-02-10
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <dataspace/client.h>
#include <region_map/client.h>
#include <pd_session/client.h>
#include <util/retry.h>
#include "device_pd.h"
void Platform::Device_pd::attach_dma_mem(Genode::Dataspace_capability ds_cap)
{
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);
/* trigger eager mapping of memory */
_pd.map(page, size);
}
catch (Out_of_ram) { throw; }
catch (Out_of_caps) { throw; }
catch (Region_map::Region_conflict) {
/*
* DMA memory already attached before.
*/
page = phys;
} catch (...) {
error(_label, ": attach_at or map failed");
}
/* sanity check */
if ((page == ~0UL) || (page != phys)) {
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));
return;
}
}
void Platform::Device_pd::assign_pci(Genode::Io_mem_dataspace_capability io_mem_cap,
Genode::uint16_t rid)
{
using namespace Genode;
Dataspace_client ds_client(io_mem_cap);
addr_t const phys = ds_client.phys_addr();
addr_t page = _address_space.attach_at(io_mem_cap, phys);
/* sanity check */
if (!page)
throw Region_map::Region_conflict();
/* trigger eager mapping of memory */
_pd.map(page, ds_client.size());
/* utility to print rid value */
struct Rid
{
Genode::uint16_t const v;
explicit Rid(Genode::uint16_t rid) : v(rid) { }
void print(Genode::Output &out) const
{
using Genode::print;
using Genode::Hex;
print(out, Hex(v >> 8, Hex::Prefix::OMIT_PREFIX), ":",
Hex((v >> 3) & 0x1f, Hex::Prefix::OMIT_PREFIX), ".",
Hex(v & 0x7, Hex::Prefix::OMIT_PREFIX));
}
};
/* 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()), " "
"virt=", Genode::Hex(page));
else
Genode::log(_label,": assignment of PCI device ", Rid(rid), " succeeded");
/* we don't need the mapping anymore */
_address_space.detach(page);
}

View File

@ -13,33 +13,87 @@
#pragma once #pragma once
#include <os/static_parent_services.h> /* base */
#include <os/slave.h> #include <base/env.h>
#include <region_map/client.h>
#include <pd_session/connection.h>
enum { STACK_SIZE = 4 * sizeof(void *) * 1024 }; /* os */
#include <io_mem_session/connection.h>
namespace Platform { class Device_pd_policy; } namespace Platform { class Device_pd; }
class Platform::Device_pd_policy class Platform::Device_pd
:
private Genode::Static_parent_services<Genode::Pd_session,
Genode::Cpu_session,
Genode::Log_session,
Genode::Rom_session>,
public Genode::Slave::Policy
{ {
private:
Genode::Pd_connection _pd;
Genode::Session_label const &_label;
/**
* Custom handling of PD-session depletion during attach operations
*
* The default implementation of 'env.rm()' automatically issues a resource
* request if the PD session quota gets exhausted. For the device PD, we don't
* want to issue resource requests but let the platform driver reflect this
* condition to its client.
*/
struct Expanding_region_map_client : Genode::Region_map_client
{
Genode::Env &_env;
Expanding_region_map_client(Genode::Env &env,
Genode::Capability<Genode::Region_map> address_space)
:
Region_map_client(address_space), _env(env)
{ }
Local_addr attach(Genode::Dataspace_capability ds,
Genode::size_t size = 0, Genode::off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (void *)0,
bool executable = false) override
{
return Genode::retry<Genode::Out_of_ram>(
[&] () {
return Genode::retry<Genode::Out_of_caps>(
[&] () {
return Region_map_client::attach(ds, size, offset,
use_local_addr,
local_addr,
executable); },
[&] () {
enum { UPGRADE_CAP_QUOTA = 2 };
if (_env.pd().avail_caps().value < UPGRADE_CAP_QUOTA)
throw;
Genode::String<32> arg("cap_quota=", (unsigned)UPGRADE_CAP_QUOTA);
_env.upgrade(Genode::Parent::Env::pd(), arg.string());
}
);
},
[&] () {
enum { UPGRADE_RAM_QUOTA = 4096 };
if (_env.ram().avail_ram().value < UPGRADE_RAM_QUOTA)
throw;
Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_RAM_QUOTA);
_env.upgrade(Genode::Parent::Env::pd(), arg.string());
}
);
}
} _address_space;
public: public:
Device_pd_policy(Genode::Rpc_entrypoint &slave_ep, Device_pd(Genode::Env &env,
Genode::Region_map &local_rm, Genode::Session_label const &label)
Genode::Pd_session &pd_ref,
Genode::Pd_session_capability pd_ref_cap,
Genode::Cap_quota cap_quota,
Genode::Ram_quota ram_quota,
Genode::Session_label const &label)
: :
Genode::Slave::Policy(label, "device_pd", *this, slave_ep, local_rm, _pd(env, label.string()),
pd_ref, pd_ref_cap, cap_quota, ram_quota) _label(label),
_address_space(env, _pd.address_space())
{ } { }
};
void attach_dma_mem(Genode::Dataspace_capability);
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);
};

View File

@ -1,224 +0,0 @@
/*
* \brief Pci device protection domain service for platform driver
* \author Alexander Boettcher
* \date 2013-02-10
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/component.h>
#include <os/static_root.h>
#include <base/log.h>
#include <base/sleep.h>
#include <dataspace/client.h>
#include <region_map/client.h>
#include <pd_session/client.h>
#include <util/flex_iterator.h>
#include <util/retry.h>
#include <nova/native_thread.h>
#include "../pci_device_pd_ipc.h"
/**
* Custom handling of PD-session depletion during attach operations
*
* The default implementation of 'env.rm()' automatically issues a resource
* request if the PD session quota gets exhausted. For the device PD, we don't
* want to issue resource requests but let the platform driver reflect this
* condition to its client.
*/
struct Expanding_region_map_client : Genode::Region_map_client
{
Genode::Env &_env;
Expanding_region_map_client(Genode::Env &env)
:
Region_map_client(env.pd().address_space()), _env(env)
{ }
Local_addr attach(Genode::Dataspace_capability ds,
Genode::size_t size, Genode::off_t offset,
bool use_local_addr,
Local_addr local_addr,
bool executable) override
{
return Genode::retry<Genode::Out_of_ram>(
[&] () {
return Genode::retry<Genode::Out_of_caps>(
[&] () {
return Region_map_client::attach(ds, size, offset,
use_local_addr,
local_addr,
executable); },
[&] () {
enum { UPGRADE_CAP_QUOTA = 2 };
if (_env.pd().avail_caps().value < UPGRADE_CAP_QUOTA)
throw;
Genode::String<32> arg("cap_quota=", (unsigned)UPGRADE_CAP_QUOTA);
_env.upgrade(Genode::Parent::Env::pd(), arg.string());
}
);
},
[&] () {
enum { UPGRADE_RAM_QUOTA = 4096 };
if (_env.ram().avail_ram().value < UPGRADE_RAM_QUOTA)
throw;
Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_RAM_QUOTA);
_env.upgrade(Genode::Parent::Env::pd(), arg.string());
}
);
}
};
static bool map_eager(Genode::addr_t const page, unsigned log2_order)
{
using Genode::addr_t;
Genode::Thread * myself = Genode::Thread::myself();
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
Nova::Rights const mapping_rw(true, true, false);
addr_t const page_fault_portal = myself->native_thread().exc_pt_sel + 14;
while (true) {
/* setup faked page fault information */
utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg()) /
sizeof(addr_t));
utcb->ip = reinterpret_cast<addr_t>(map_eager);
utcb->qual[1] = page;
utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw);
/* trigger faked page fault */
Genode::uint8_t res = Nova::call(page_fault_portal);
bool const retry = utcb->msg_words();
if (res != Nova::NOVA_OK || !retry)
return res == Nova::NOVA_OK;
};
}
void Platform::Device_pd_component::attach_dma_mem(Genode::Dataspace_capability ds_cap)
{
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); }
catch (Out_of_ram) { throw; }
catch (Out_of_caps) { throw; }
catch (Region_map::Region_conflict) {
/*
* DMA memory already attached before or collision with normal
* device_pd memory (text, data, etc).
* Currently we can't distinguish it easily - show error
* message as a precaution.
*/
Genode::error("region conflict");
} catch (...) { }
/* sanity check */
if ((page == ~0UL) || (page != phys)) {
if (page != ~0UL)
_address_space.detach(page);
Genode::error("attachment of DMA memory @ ",
Genode::Hex(phys), "+", Genode::Hex(size), " failed");
return;
}
Genode::Flexpage_iterator it(page, size, page, size, 0);
for (Genode::Flexpage flex = it.page(); flex.valid(); flex = it.page()) {
if (map_eager(flex.addr, flex.log2_order))
continue;
Genode::error("attachment of DMA memory @ ",
Genode::Hex(phys), "+", Genode::Hex(size), " failed at ",
flex.addr);
return;
}
}
void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capability io_mem_cap,
Genode::uint16_t rid)
{
using namespace Genode;
Dataspace_client ds_client(io_mem_cap);
addr_t page = _address_space.attach(io_mem_cap);
/* sanity check */
if (!page)
throw Region_map::Region_conflict();
/* trigger mapping of whole memory area */
if (!map_eager(page, 12))
Genode::error("assignment of PCI device failed - ", Genode::Hex(page));
/* utility to print rid value */
struct Rid
{
Genode::uint16_t const v;
explicit Rid(Genode::uint16_t rid) : v(rid) { }
void print(Genode::Output &out) const
{
using Genode::print;
using Genode::Hex;
print(out, Hex(v >> 8, Hex::Prefix::OMIT_PREFIX), ":",
Hex((v >> 3) & 0x1f, Hex::Prefix::OMIT_PREFIX), ".",
Hex(v & 0x7, Hex::Prefix::OMIT_PREFIX));
}
};
/* try to assign pci device to this protection domain */
if (!_env.pd().assign_pci(page, rid))
Genode::error("assignment of PCI device ", Rid(rid), " failed ",
"phys=", Genode::Hex(ds_client.phys_addr()), " "
"virt=", Genode::Hex(page));
else
Genode::log("assignment of PCI device ", Rid(rid), " succeeded");
/* we don't need the mapping anymore */
_address_space.detach(page);
}
struct Main
{
Genode::Env &env;
Expanding_region_map_client rm { env };
Platform::Device_pd_component pd_component { rm, env };
Genode::Static_root<Platform::Device_pd> root { env.ep().manage(pd_component) };
Main(Genode::Env &env) : env(env)
{
env.parent().announce(env.ep().manage(root));
}
};
/***************
** Component **
***************/
void Component::construct(Genode::Env &env) { static Main main(env); }

View File

@ -1,6 +0,0 @@
TARGET = device_pd
SRC_CC = main.cc
LIBS = base-nova
REQUIRES = nova

View File

@ -1,85 +0,0 @@
/*
* \brief IPC interface between pci_drv and pci_device_pd
* \author Alexander Boettcher
* \date 2013-02-15
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#pragma once
#include <base/connection.h>
#include <base/rpc_server.h>
#include <io_mem_session/capability.h>
namespace Platform {
struct Device_pd;
struct Device_pd_client;
struct Device_pd_connection;
struct Device_pd_component;
}
struct Platform::Device_pd : Genode::Session
{
static const char *service_name() { return "DEVICE_PD"; }
enum { CAP_QUOTA = 2 };
typedef Device_pd_client Client;
GENODE_RPC_THROW(Rpc_attach_dma_mem, void, attach_dma_mem,
GENODE_TYPE_LIST(Genode::Out_of_ram, Genode::Out_of_caps),
Genode::Dataspace_capability);
GENODE_RPC_THROW(Rpc_assign_pci, void, assign_pci,
GENODE_TYPE_LIST(Genode::Out_of_ram, Genode::Out_of_caps,
Genode::Region_map::Region_conflict),
Genode::Io_mem_dataspace_capability, Genode::uint16_t);
GENODE_RPC_INTERFACE(Rpc_attach_dma_mem, Rpc_assign_pci);
};
struct Platform::Device_pd_client : Genode::Rpc_client<Device_pd>
{
Device_pd_client(Capability<Device_pd> cap)
: Rpc_client<Device_pd>(cap) { }
void attach_dma_mem(Genode::Dataspace_capability cap) {
call<Rpc_attach_dma_mem>(cap); }
void assign_pci(Genode::Io_mem_dataspace_capability cap,
Genode::uint16_t bdf)
{
call<Rpc_assign_pci>(cap, bdf);
}
};
struct Platform::Device_pd_connection : Genode::Connection<Device_pd>, Device_pd_client
{
enum { RAM_QUOTA = 0UL };
Device_pd_connection(Genode::Capability<Device_pd> cap)
:
Genode::Connection<Device_pd>(cap),
Device_pd_client(cap)
{ }
};
struct Platform::Device_pd_component : Genode::Rpc_object<Device_pd,
Device_pd_component>
{
Genode::Env &_env;
Genode::Region_map &_address_space;
Device_pd_component(Genode::Region_map &address_space, Genode::Env &env)
: _env(env), _address_space(address_space) { }
void attach_dma_mem(Genode::Dataspace_capability);
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);
};

View File

@ -15,9 +15,10 @@
/* base */ /* base */
#include <base/allocator_guard.h> #include <base/allocator_guard.h>
#include <base/attached_rom_dataspace.h>
#include <base/heap.h>
#include <base/rpc_server.h> #include <base/rpc_server.h>
#include <base/tslab.h> #include <base/tslab.h>
#include <base/attached_rom_dataspace.h>
#include <ram_session/capability.h> #include <ram_session/capability.h>
#include <root/component.h> #include <root/component.h>
@ -35,7 +36,6 @@
/* local */ /* local */
#include "pci_device_component.h" #include "pci_device_component.h"
#include "pci_config_access.h" #include "pci_config_access.h"
#include "pci_device_pd_ipc.h"
#include "device_pd.h" #include "device_pd.h"
namespace Platform { namespace Platform {
@ -199,13 +199,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
private: private:
Genode::Env &_env; Genode::Env &_env;
Genode::Rpc_entrypoint &_device_pd_ep;
Genode::Attached_rom_dataspace &_config; Genode::Attached_rom_dataspace &_config;
Genode::Ram_session_guard _env_ram; Genode::Ram_session_guard _env_ram;
Genode::Ram_session_capability _env_ram_cap;
Genode::Pd_session &_env_pd;
Genode::Pd_session_capability _env_pd_cap;
Genode::Region_map &_local_rm;
Genode::Heap _md_alloc; Genode::Heap _md_alloc;
Genode::Session_label const _label; Genode::Session_label const _label;
Genode::Session_policy const _policy { _label, _config.xml() }; Genode::Session_policy const _policy { _label, _config.xml() };
@ -237,145 +232,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
return false; return false;
} }
/** Platform::Device_pd _device_pd { _env, _label };
* Deduce specified amount of quota from an allocator guard, or throw
* an 'Out_of_ram' exception if the guard's quota is depleted.
*/
struct Quota_reservation
{
Genode::Ram_session_guard &guard;
Genode::size_t const amount;
Quota_reservation(Genode::Ram_session_guard &guard,
Genode::size_t amount)
: guard(guard), amount(amount)
{
if (!guard.withdraw(amount))
throw Out_of_ram();
}
~Quota_reservation() noexcept(false)
{
if (!guard.revert_withdraw(amount))
throw Fatal();
}
};
class Device_pd
{
public:
class Startup_failed : Genode::Exception { };
private:
enum { CAP_QUOTA = 60, RAM_QUOTA = 190 * 4096 };
Quota_reservation const _reservation;
Device_pd_policy _policy;
Genode::Child _child;
void _check_child_started_up() const {
if (!_child.active())
throw Startup_failed(); }
bool const _active = (_check_child_started_up(), true);
Genode::Slave::Connection<Device_pd_connection> _connection;
public:
/**
* Constructor
*
* \throw Out_of_ram
* \throw Out_of_caps
* \throw Startup_failed child could not be started
* \throw Service_denied by 'Slave::Connection'
*/
Device_pd(Genode::Region_map &local_rm,
Genode::Rpc_entrypoint &ep,
Genode::Ram_session_guard &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Genode::Pd_session &ref_pd,
Genode::Pd_session_capability ref_pd_cap,
Genode::Session_label const &label)
try :
_reservation(ref_ram, RAM_QUOTA),
_policy(ep, local_rm, ref_pd, ref_pd_cap,
Genode::Cap_quota{CAP_QUOTA},
Genode::Ram_quota{RAM_QUOTA},
label),
_child(local_rm, ep, _policy),
_connection(_policy, Genode::Slave::Args())
{ }
/* thrown by 'Quota_reservation', 'Device_pd_policy' or 'Child' */
catch (Genode::Out_of_ram) {
throw; }
catch (Genode::Out_of_caps) {
Genode::warning("Out_of_caps during device-pd creation");
throw; }
/* thrown by 'Slave::Connection' */
catch (Genode::Insufficient_ram_quota) {
throw Genode::Out_of_ram(); }
/* thrown by 'Slave::Connection' */
catch (Genode::Insufficient_cap_quota) {
Genode::warning("Insufficient_cap_quota during device-pd creation");
throw Genode::Out_of_caps(); }
Device_pd_client &session() { return _connection; }
Genode::Ram_session_capability ram_session_cap() {
return _child.ram_session_cap(); }
};
Device_pd *_device_pd = nullptr;
/**
* Free device PD at session destruction
*/
struct Device_pd_guard
{
Session_component &session;
~Device_pd_guard() {
if (session._device_pd)
Genode::destroy(session._md_alloc, session._device_pd); }
} _device_pd_guard { *this };
/**
* Attempt to initialize device PD
*
* \throw Out_of_ram session quota does not suffice to spawn the
* device PD
* \throw Out_of_caps
*/
void _try_init_device_pd()
{
if (_device_pd || _no_device_pd)
return;
try {
_device_pd = new (_md_alloc)
Device_pd(_local_rm, _device_pd_ep, _env_ram, _env_ram_cap,
_env_pd, _env_pd_cap, _label);
}
catch (Genode::Out_of_ram) { /* thrown by '_md_alloc', 'Device_pd' */
throw; }
catch (Genode::Out_of_caps) {
Genode::warning("Out_of_caps during Device_pd construction");
throw; }
catch (...) {
Genode::warning("PCI device protection domain for IOMMU support "
"is not available");
_no_device_pd = true;
}
}
enum { MAX_PCI_DEVICES = Device_config::MAX_BUSES * enum { MAX_PCI_DEVICES = Device_config::MAX_BUSES *
Device_config::MAX_DEVICES * Device_config::MAX_DEVICES *
@ -383,12 +240,11 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
static Genode::Bit_array<MAX_PCI_DEVICES> bdf_in_use; static Genode::Bit_array<MAX_PCI_DEVICES> bdf_in_use;
/** /**
* List containing extended PCI config space information * List containing extended PCI config space information
*/ */
static Genode::List<Config_space> &config_space_list() { static Genode::List<Config_space> &config_space_list()
{
static Genode::List<Config_space> config_space; static Genode::List<Config_space> config_space;
return config_space; return config_space;
} }
@ -398,8 +254,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
* the corresponding extended 4K PCI config space address. * the corresponding extended 4K PCI config space address.
* A io mem dataspace is created and returned. * A io mem dataspace is created and returned.
*/ */
Genode::addr_t Genode::addr_t lookup_config_space(Genode::uint16_t const bdf)
lookup_config_space(Genode::uint16_t const bdf)
{ {
using namespace Genode; using namespace Genode;
@ -416,7 +271,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
* List of aliases for PCI Class/Subclas/Prog I/F triple used * List of aliases for PCI Class/Subclas/Prog I/F triple used
* by xml config for this platform driver * by xml config for this platform driver
*/ */
unsigned class_subclass_prog(const char * name) { unsigned class_subclass_prog(const char * name)
{
using namespace Genode; using namespace Genode;
static struct { static struct {
@ -591,18 +447,13 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
*/ */
Session_component(Genode::Env &env, Session_component(Genode::Env &env,
Genode::Attached_rom_dataspace &config, Genode::Attached_rom_dataspace &config,
Genode::Rpc_entrypoint &device_pd_ep,
Platform::Pci_buses &buses, Platform::Pci_buses &buses,
Genode::Heap &global_heap, Genode::Heap &global_heap,
char const *args) char const *args)
: :
_env(env), _device_pd_ep(device_pd_ep), _env(env),
_config(config), _config(config),
_env_ram(env.ram(), Genode::ram_quota_from_args(args).value), _env_ram(env.ram(), Genode::ram_quota_from_args(args).value),
_env_ram_cap(env.ram_session_cap()),
_env_pd(env.pd()),
_env_pd_cap(env.pd_session_cap()),
_local_rm(env.rm()),
_md_alloc(_env_ram, env.rm()), _md_alloc(_env_ram, env.rm()),
_label(Genode::label_from_args(args)), _label(Genode::label_from_args(args)),
_pci_bus(buses), _global_heap(global_heap) _pci_bus(buses), _global_heap(global_heap)
@ -900,17 +751,13 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
Io_mem_dataspace_capability io_mem = device->get_config_space(); Io_mem_dataspace_capability io_mem = device->get_config_space();
_try_init_device_pd();
if (!_device_pd)
return;
try { try {
_device_pd->session().assign_pci(io_mem, device->config().bdf()); _device_pd.assign_pci(io_mem, device->config().bdf());
for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) {
Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config()); Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config());
if (rmrr_cap.valid()) if (rmrr_cap.valid())
_device_pd->session().attach_dma_mem(rmrr_cap); _device_pd.attach_dma_mem(rmrr_cap);
} }
} catch (...) { } catch (...) {
Genode::error("assignment to device pd or of RMRR region failed"); Genode::error("assignment to device pd or of RMRR region failed");
@ -938,13 +785,6 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t const size) override Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t const size) override
{ {
/*
* We always try to create the device PD first because
* otherwise we might consume the requested size multiple
* times which breaks our accounting.
*/
_try_init_device_pd();
Ram_capability ram_cap; Ram_capability ram_cap;
try { ram_cap = _env_ram.alloc(size, Genode::UNCACHED); } try { ram_cap = _env_ram.alloc(size, Genode::UNCACHED); }
@ -953,13 +793,11 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
if (!ram_cap.valid()) if (!ram_cap.valid())
return ram_cap; return ram_cap;
if (_device_pd) { try { _device_pd.attach_dma_mem(ram_cap); }
try { _device_pd->session().attach_dma_mem(ram_cap); } catch (Out_of_ram) { _rollback(size, ram_cap);; }
catch (Out_of_ram) { _rollback(size, ram_cap);; } catch (Out_of_caps) {
catch (Out_of_caps) { Genode::warning("Out_of_caps while attaching DMA memory");
Genode::warning("Out_of_caps while attaching DMA memory"); _rollback(size, ram_cap);;
_rollback(size, ram_cap);;
}
} }
try { _insert(ram_cap); } try { _insert(ram_cap); }
@ -1014,7 +852,6 @@ class Platform::Root : public Genode::Root_component<Session_component>
Genode::Reporter _pci_reporter { _env, "pci" }; Genode::Reporter _pci_reporter { _env, "pci" };
Genode::Rpc_entrypoint _device_pd_ep;
Genode::Heap _heap { _env.ram(), _env.rm() }; Genode::Heap _heap { _env.ram(), _env.rm() };
Platform::Pci_buses _buses { _env, _heap }; Platform::Pci_buses _buses { _env, _heap };
@ -1061,7 +898,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
} }
if (node.has_type("rmrr")) { if (node.has_type("rmrr")) {
uint64_t mem_start, mem_end; uint64_t mem_start = 0, mem_end = 0;
node.attribute("start").value(&mem_start); node.attribute("start").value(&mem_start);
node.attribute("end").value(&mem_end); node.attribute("end").value(&mem_end);
@ -1076,7 +913,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
if (!scope.num_sub_nodes() || !scope.has_type("scope")) if (!scope.num_sub_nodes() || !scope.has_type("scope"))
throw 3; throw 3;
unsigned bus, dev, func; unsigned bus = 0, dev = 0, func = 0;
scope.attribute("bus_start").value(&bus); scope.attribute("bus_start").value(&bus);
for (unsigned p = 0; p < scope.num_sub_nodes(); p++) { for (unsigned p = 0; p < scope.num_sub_nodes(); p++) {
@ -1152,7 +989,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
{ {
try { try {
return new (md_alloc()) return new (md_alloc())
Session_component(_env, _config, _device_pd_ep, _buses, _heap, args); Session_component(_env, _config, _buses, _heap, args);
} }
catch (Genode::Session_policy::No_policy_defined) { catch (Genode::Session_policy::No_policy_defined) {
Genode::error("Invalid session request, no matching policy for ", Genode::error("Invalid session request, no matching policy for ",
@ -1184,8 +1021,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
: :
Genode::Root_component<Session_component>(&env.ep().rpc_ep(), Genode::Root_component<Session_component>(&env.ep().rpc_ep(),
&md_alloc), &md_alloc),
_env(env), _config(config), _env(env), _config(config)
_device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave")
{ {
if (acpi_rom) { if (acpi_rom) {
try { try {

View File

@ -1,6 +1,7 @@
TARGET = platform_drv TARGET = platform_drv
REQUIRES = x86 REQUIRES = x86
SRC_CC = main.cc irq.cc pci_device.cc nonpci_devices.cc session.cc SRC_CC = main.cc irq.cc pci_device.cc nonpci_devices.cc session.cc
SRC_CC += device_pd.cc
LIBS = base LIBS = base
INC_DIR = $(PRG_DIR) INC_DIR = $(PRG_DIR)