mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
parent
b902f42482
commit
4c4e7c64d0
@ -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())
|
||||
{ }
|
||||
};
|
||||
|
74
repos/os/src/drivers/platform/spec/x86/device_pd.h
Normal file
74
repos/os/src/drivers/platform/spec/x86/device_pd.h
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user