x86: start per platform session separate device_pd

Issue #1539
This commit is contained in:
Alexander Boettcher 2015-11-05 22:15:50 +01:00 committed by Christian Helmuth
parent b902f42482
commit 4c4e7c64d0
4 changed files with 135 additions and 112 deletions

View File

@ -23,7 +23,7 @@ struct Platform::Connection : Genode::Connection<Session>, Client
{
Connection()
:
Genode::Connection<Session>(session("ram_quota=12K")),
Genode::Connection<Session>(session("ram_quota=20K")),
Client(cap())
{ }
};

View File

@ -0,0 +1,74 @@
/*
* \brief Device PD handling for the platform driver
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#pragma once
#include <os/slave.h>
enum {
DEVICE_PD_RAM_QUOTA = 256 * 4096,
STACK_SIZE = 2 * sizeof(void *)*1024
};
namespace Platform { class Device_pd_policy; }
class Platform::Device_pd_policy : public Genode::Slave_policy
{
private:
Genode::Root_capability _cap;
Genode::Lock _lock;
Genode::Slave _device_pd_slave;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = { "LOG", "CAP", "RM", 0 };
return permitted_services;
};
public:
Device_pd_policy(Genode::Rpc_entrypoint &slave_ep)
:
Slave_policy("device_pd", slave_ep),
_lock(Genode::Lock::LOCKED),
_device_pd_slave(slave_ep, *this, DEVICE_PD_RAM_QUOTA)
{ }
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
/* wait for 'platform_drv' to announce the DEVICE_PD service */
if (Genode::strcmp(service_name, "DEVICE_PD"))
return false;
_cap = root;
_lock.unlock();
return true;
}
Genode::Root_capability root() {
if (!_cap.valid())
_lock.lock();
return _cap;
}
};

View File

@ -16,63 +16,15 @@
#include <base/sleep.h>
#include <cap_session/connection.h>
#include <os/slave.h>
#include <os/attached_rom_dataspace.h>
#include "pci_session_component.h"
#include "pci_device_config.h"
#include "device_pd.h"
using namespace Genode;
using namespace Platform;
class Device_pd_policy : public Genode::Slave_policy
{
private:
Genode::Root_capability _cap;
Genode::Lock _lock;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = { "LOG", "CAP", "RM",
"CPU", 0 };
return permitted_services;
};
public:
Device_pd_policy(Genode::Rpc_entrypoint &slave_ep)
:
Slave_policy("device_pd", slave_ep),
_lock(Genode::Lock::LOCKED)
{ }
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
/* wait for 'platform_drv' to announce the DEVICE_PD service */
if (Genode::strcmp(service_name, "DEVICE_PD"))
return false;
_cap = root;
_lock.unlock();
return true;
}
Genode::Root_capability root() {
if (!_cap.valid())
_lock.lock();
return _cap;
}
};
int main(int argc, char **argv)
{
printf("platform driver started\n");
@ -80,27 +32,9 @@ int main(int argc, char **argv)
/*
* Initialize server entry point
*/
enum {
STACK_SIZE = 2 * sizeof(addr_t)*1024,
DEVICE_PD_RAM_QUOTA = 256 * 4096,
};
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "platform_ep");
/* use 'device_pd' as slave service */
Session_capability session_dev_pd;
Genode::Root_capability device_pd_root;
try {
static Rpc_entrypoint device_pd_ep(&cap, STACK_SIZE, "device_pd_slave");
static Device_pd_policy device_pd_policy(device_pd_ep);
static Genode::Slave device_pd_slave(device_pd_ep, device_pd_policy,
DEVICE_PD_RAM_QUOTA);
device_pd_root = device_pd_policy.root();
} catch (...) {
PWRN("PCI device protection domain for IOMMU support is not available");
}
/*
* Use sliced heap to allocate each session component at a separate
* dataspace.
@ -140,8 +74,7 @@ int main(int argc, char **argv)
/*
* Let the entry point serve the PCI root interface
*/
static Platform::Root root(&ep, &sliced_heap, DEVICE_PD_RAM_QUOTA,
device_pd_root, report_addr);
static Platform::Root root(&ep, &sliced_heap, report_addr, cap);
env()->parent()->announce(ep.manage(&root));

View File

@ -17,6 +17,7 @@
#include <base/allocator_guard.h>
#include <base/rpc_server.h>
#include <base/tslab.h>
#include <cap_session/connection.h>
#include <ram_session/connection.h>
#include <root/component.h>
@ -33,6 +34,7 @@
#include "pci_device_component.h"
#include "pci_config_access.h"
#include "pci_device_pd_ipc.h"
#include "device_pd.h"
namespace Platform {
bool bus_valid(int bus = 0);
@ -116,8 +118,36 @@ namespace Platform {
Genode::Allocator_guard _md_alloc;
Genode::Tslab<Device_component, 4096 - 64> _device_slab;
Genode::List<Device_component> _device_list;
Device_pd_client _child;
Genode::Ram_connection *_ram;
struct Devicepd {
Platform::Device_pd_policy *policy;
Device_pd_client child;
Devicepd (Genode::Rpc_entrypoint &ep,
Genode::Allocator_guard &md_alloc)
:
policy(nullptr),
child(Genode::reinterpret_cap_cast<Device_pd>(Genode::Native_capability()))
{
try {
policy = new (md_alloc) Device_pd_policy(ep);
using Genode::Session_capability;
using Genode::Affinity;
Session_capability session = Genode::Root_client(policy->root()).session("", Affinity());
child = Device_pd_client(Genode::reinterpret_cap_cast<Device_pd>(session));
} catch (Genode::Rom_connection::Rom_connection_failed) {
PWRN("PCI device protection domain for IOMMU support "
"is not available");
}
}
bool valid() { return policy && policy->root().valid(); }
} _device_pd;
Genode::Ram_connection _ram;
Genode::Session_label _label;
Genode::Session_policy _policy;
@ -377,15 +407,22 @@ namespace Platform {
*/
Session_component(Genode::Rpc_entrypoint *ep,
Genode::Allocator *md_alloc,
Genode::Root_capability &device_pd_root,
Genode::Ram_connection *ram,
const char *args)
const char *args,
Genode::Rpc_entrypoint &device_pd_ep)
:
_ep(ep),
_md_alloc(md_alloc, Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
_device_slab(&_md_alloc), _child(Genode::reinterpret_cap_cast<Device_pd>(Genode::Native_capability())),
_ram(ram), _label(args), _policy(_label)
_device_slab(&_md_alloc),
_device_pd(device_pd_ep, _md_alloc),
/* restrict physical address to 3G on 32bit with device_pd */
_ram("dma", 0, (_device_pd.valid() && sizeof(void *) == 4)
? 0xc0000000UL : 0x100000000ULL),
_label(args), _policy(_label)
{
/* associate _ram session with platform_drv _ram session */
_ram.ref_account(Genode::env()->ram_session_cap());
Genode::env()->ram_session()->transfer_quota(_ram.cap(), 0x1000);
/* non-pci devices */
_policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) {
try {
@ -406,15 +443,6 @@ namespace Platform {
throw Genode::Root::Unavailable();
});
if (device_pd_root.valid()) {
using Genode::Session_capability;
using Genode::Affinity;
Session_capability session = Genode::Root_client(device_pd_root).session("", Affinity());
Genode::Capability <Device_pd> cap = Genode::reinterpret_cap_cast<Device_pd>(session);
_child = Device_pd_client(cap);
}
/* pci devices */
_policy.for_each_sub_node("pci", [&] (Genode::Xml_node node) {
enum { INVALID_CLASS = 0x1000000U };
@ -671,15 +699,15 @@ namespace Platform {
Io_mem_dataspace_capability io_mem = device->get_config_space();
if (!_child.valid())
if (!_device_pd.child.valid())
return Io_mem_dataspace_capability();
_child.assign_pci(io_mem);
_device_pd.child.assign_pci(io_mem);
for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) {
Io_mem_dataspace_capability rmrr_cap = r->match(device->config());
if (rmrr_cap.valid())
_child.attach_dma_mem(rmrr_cap);
_device_pd.child.attach_dma_mem(rmrr_cap);
}
/*
@ -709,7 +737,7 @@ namespace Platform {
throw Device::Quota_exceeded();
Genode::Ram_session * const rs = Genode::env()->ram_session();
if (rs->transfer_quota(_ram->cap(), size)) {
if (rs->transfer_quota(_ram.cap(), size)) {
_md_alloc.upgrade(size);
return Ram_capability();
}
@ -717,20 +745,20 @@ namespace Platform {
Ram_capability ram_cap;
try {
ram_cap = Genode::retry<Genode::Ram_session::Out_of_metadata>(
[&] () { return _ram->alloc(size, Genode::UNCACHED); },
[&] () { Genode::env()->parent()->upgrade(_ram->cap(), "ram_quota=4K"); });
[&] () { return _ram.alloc(size, Genode::UNCACHED); },
[&] () { Genode::env()->parent()->upgrade(_ram.cap(), "ram_quota=4K"); });
} catch (Genode::Ram_session::Quota_exceeded) { }
if (!ram_cap.valid()) {
_ram->transfer_quota(Genode::env()->ram_session_cap(), size);
_ram.transfer_quota(Genode::env()->ram_session_cap(), size);
_md_alloc.upgrade(size);
return ram_cap;
}
if (!_child.valid())
if (!_device_pd.child.valid())
return ram_cap;
_child.attach_dma_mem(ram_cap);
_device_pd.child.attach_dma_mem(ram_cap);
return ram_cap;
}
@ -738,7 +766,7 @@ namespace Platform {
void free_dma_buffer(Ram_capability ram)
{
if (ram.valid())
_ram->free(ram);
_ram.free(ram);
}
Device_capability device(String const &name) override;
@ -749,9 +777,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
{
private:
Genode::Root_capability _device_pd_root;
/* Ram_session for allocation of dma capable dataspaces */
Genode::Ram_connection _ram;
Genode::Rpc_entrypoint _device_pd_ep;
void _parse_report_rom(const char * acpi_rom)
{
@ -884,8 +910,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
{
try {
return new (md_alloc()) Session_component(ep(), md_alloc(),
_device_pd_root,
&_ram, args);
args, _device_pd_ep);
} catch (Genode::Session_policy::No_policy_defined) {
PERR("Invalid session request, no matching policy for '%s'",
Genode::Session_label(args).string());
@ -900,7 +925,6 @@ class Platform::Root : public Genode::Root_component<Session_component>
s->upgrade_ram_quota(ram_quota);
}
public:
/**
@ -912,14 +936,10 @@ class Platform::Root : public Genode::Root_component<Session_component>
* components and PCI-device components
*/
Root(Genode::Rpc_entrypoint *ep, Genode::Allocator *md_alloc,
Genode::size_t pci_device_pd_ram_quota,
Genode::Root_capability &device_pd_root, const char *acpi_rom)
const char *acpi_rom, Genode::Cap_connection &cap)
:
Genode::Root_component<Session_component>(ep, md_alloc),
_device_pd_root(device_pd_root),
/* restrict physical address to 3G on 32bit with device_pd */
_ram("dma", 0, (device_pd_root.valid() && sizeof(void *) == 4) ?
0xc0000000UL : 0x100000000ULL)
_device_pd_ep(&cap, STACK_SIZE, "device_pd_slave")
{
/* enforce initial bus scan */
bus_valid();
@ -931,9 +951,5 @@ class Platform::Root : public Genode::Root_component<Session_component>
PERR("PCI config space data could not be parsed.");
}
}
/* associate _ram session with ram_session of process */
_ram.ref_account(Genode::env()->ram_session_cap());
Genode::env()->ram_session()->transfer_quota(_ram.cap(), 0x1000);
}
};