mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
pci: add device_pd functionality
This commit is contained in:
parent
2123f3f7e8
commit
e05adecfab
@ -163,8 +163,9 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
char const **_permitted_services() const
|
||||
{
|
||||
static char const *permitted_services[] = { "CPU", "CAP", "RM",
|
||||
"LOG", "IO_PORT",
|
||||
"SIGNAL", 0};
|
||||
"LOG", "IO_PORT", "PD",
|
||||
"ROM", "RAM", "SIGNAL",
|
||||
"IO_MEM", 0 };
|
||||
return permitted_services;
|
||||
};
|
||||
|
||||
|
95
os/src/drivers/pci/device_pd/main.cc
Normal file
95
os/src/drivers/pci/device_pd/main.cc
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Pci device protection domain service for pci_drv
|
||||
* \author Alexander Boettcher
|
||||
* \date 2013-02-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2013 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.
|
||||
*/
|
||||
|
||||
#include <os/static_root.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
#include <cap_session/connection.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <pd_session/client.h>
|
||||
|
||||
#include <util/touch.h>
|
||||
|
||||
#include "../pci_device_pd_ipc.h"
|
||||
|
||||
|
||||
void Pci::Device_pd_component::attach_dma_mem(Genode::Ram_dataspace_capability ds_cap)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Dataspace_client ds_client(ds_cap);
|
||||
|
||||
addr_t page = env()->rm_session()->attach_at(ds_cap, ds_client.phys_addr());
|
||||
/* sanity check */
|
||||
if (page != ds_client.phys_addr())
|
||||
throw Rm_session::Region_conflict();
|
||||
|
||||
/* trigger mapping of whole memory area */
|
||||
for (size_t rounds = (ds_client.size() + 1) / 4096; rounds;
|
||||
page += 4096, rounds --)
|
||||
touch_read(reinterpret_cast<unsigned char *>(page));
|
||||
}
|
||||
|
||||
void Pci::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capability io_mem_cap)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Dataspace_client ds_client(io_mem_cap);
|
||||
|
||||
addr_t page = env()->rm_session()->attach(io_mem_cap);
|
||||
/* sanity check */
|
||||
if (!page)
|
||||
throw Rm_session::Region_conflict();
|
||||
|
||||
/* trigger mapping of whole memory area */
|
||||
touch_read(reinterpret_cast<unsigned char *>(page));
|
||||
|
||||
/* try to assign pci device to this protection domain */
|
||||
if (!env()->pd_session()->assign_pci(page))
|
||||
PERR("assignment of PCI device failed");
|
||||
|
||||
/* we don't need the mapping anymore */
|
||||
env()->rm_session()->detach(page);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Genode::printf("PCI device pd starting ...\n");
|
||||
|
||||
/*
|
||||
* Initialize server entry point
|
||||
*/
|
||||
enum {
|
||||
STACK_SIZE = 4096
|
||||
};
|
||||
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "pci_device_pd_ep");
|
||||
|
||||
static Pci::Device_pd_component pci_device_component;
|
||||
|
||||
/*
|
||||
* Attach input root interface to the entry point
|
||||
*/
|
||||
static Static_root<Pci::Device_pd> root(ep.manage(&pci_device_component));
|
||||
|
||||
env()->parent()->announce(ep.manage(&root));
|
||||
|
||||
printf("PCI device pd started\n");
|
||||
|
||||
Genode::sleep_forever();
|
||||
return 0;
|
||||
}
|
6
os/src/drivers/pci/device_pd/target.mk
Normal file
6
os/src/drivers/pci/device_pd/target.mk
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET = pci_device_pd
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
|
||||
REQUIRES = nova
|
||||
|
@ -16,12 +16,62 @@
|
||||
#include <base/sleep.h>
|
||||
#include <cap_session/connection.h>
|
||||
|
||||
#include <os/slave.h>
|
||||
|
||||
#include "pci_session_component.h"
|
||||
#include "pci_device_config.h"
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Pci;
|
||||
|
||||
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("pci_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 'pci_drv' to announce the PCI service */
|
||||
if (Genode::strcmp(service_name, "PCI_DEV_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("PCI driver started\n");
|
||||
@ -29,10 +79,26 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Initialize server entry point
|
||||
*/
|
||||
enum { STACK_SIZE = 2 * sizeof(addr_t)*1024 };
|
||||
enum {
|
||||
STACK_SIZE = 2 * sizeof(addr_t)*1024,
|
||||
PCI_DEVICE_PD_RAM_QUOTA = 512 * 1024,
|
||||
};
|
||||
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "pci_ep");
|
||||
|
||||
/* use 'pci_device_pd' as slave service */
|
||||
Session_capability session_dev_pd;
|
||||
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,
|
||||
PCI_DEVICE_PD_RAM_QUOTA);
|
||||
session_dev_pd = Genode::Root_client(device_pd_policy.root()).session("");
|
||||
} catch (...) {
|
||||
PWRN("PCI device protection domain for IOMMU support is not available");
|
||||
}
|
||||
|
||||
/*
|
||||
* Use sliced heap to allocate each session component at a separate
|
||||
* dataspace.
|
||||
@ -42,7 +108,8 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Let the entry point serve the PCI root interface
|
||||
*/
|
||||
static Pci::Root root(&ep, &sliced_heap);
|
||||
static Pci::Root root(&ep, &sliced_heap, PCI_DEVICE_PD_RAM_QUOTA,
|
||||
Genode::reinterpret_cap_cast<Device_pd>(session_dev_pd));
|
||||
env()->parent()->announce(ep.manage(&root));
|
||||
|
||||
sleep_forever();
|
||||
|
57
os/src/drivers/pci/pci_device_pd_ipc.h
Normal file
57
os/src/drivers/pci/pci_device_pd_ipc.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* \brief IPC interface between pci_drv and pci_device_pd
|
||||
* \author Alexander Boettcher
|
||||
* \date 2013-02-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2013 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.
|
||||
*/
|
||||
|
||||
#ifndef _PCI_DEVICE_PD_IPC_H_
|
||||
#define _PCI_DEVICE_PD_IPC_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
#include <io_mem_session/capability.h>
|
||||
#include <ram_session/ram_session.h>
|
||||
|
||||
namespace Pci {
|
||||
|
||||
struct Device_pd : Genode::Session
|
||||
{
|
||||
static const char *service_name() { return "PCI_DEV_PD"; }
|
||||
|
||||
GENODE_RPC(Rpc_attach_dma_mem, void, attach_dma_mem,
|
||||
Genode::Ram_dataspace_capability);
|
||||
GENODE_RPC(Rpc_assign_pci, void, assign_pci,
|
||||
Genode::Io_mem_dataspace_capability);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_attach_dma_mem, Rpc_assign_pci);
|
||||
};
|
||||
|
||||
struct 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::Ram_dataspace_capability cap) {
|
||||
call<Rpc_attach_dma_mem>(cap); }
|
||||
|
||||
void assign_pci(Genode::Io_mem_dataspace_capability cap) {
|
||||
call<Rpc_assign_pci>(cap); }
|
||||
};
|
||||
|
||||
struct Device_pd_component : Genode::Rpc_object<Device_pd,
|
||||
Device_pd_component>
|
||||
{
|
||||
void attach_dma_mem(Genode::Ram_dataspace_capability);
|
||||
void assign_pci(Genode::Io_mem_dataspace_capability);
|
||||
};
|
||||
|
||||
}
|
||||
#endif /* _PCI_DEVICE_PD_IPC_H_ */
|
@ -24,11 +24,12 @@
|
||||
|
||||
#include "pci_device_component.h"
|
||||
#include "pci_config_access.h"
|
||||
#include "pci_device_pd_ipc.h"
|
||||
|
||||
namespace Pci {
|
||||
|
||||
/**
|
||||
* Check if given PCI bus was found on inital scan
|
||||
* Check if given PCI bus was found on initial scan
|
||||
*
|
||||
* This tremendously speeds up further scans by other drivers.
|
||||
*/
|
||||
@ -80,9 +81,10 @@ namespace Pci {
|
||||
Genode::Rpc_entrypoint *_ep;
|
||||
Genode::Allocator *_md_alloc;
|
||||
Genode::List<Device_component> _device_list;
|
||||
Device_pd_client *_child;
|
||||
|
||||
/**
|
||||
* Scan PCI busses for a device
|
||||
* Scan PCI buses for a device
|
||||
*
|
||||
* \param bus start scanning at bus number
|
||||
* \param device start scanning at device number
|
||||
@ -157,8 +159,10 @@ namespace Pci {
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Genode::Rpc_entrypoint *ep,
|
||||
Genode::Allocator *md_alloc):
|
||||
_ep(ep), _md_alloc(md_alloc) { }
|
||||
Genode::Allocator *md_alloc,
|
||||
Device_pd_client *child)
|
||||
:
|
||||
_ep(ep), _md_alloc(md_alloc), _child(child) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@ -231,6 +235,7 @@ namespace Pci {
|
||||
/* lookup if we have a extended pci config space */
|
||||
Genode::addr_t config_space = lookup_config_space(bus, device,
|
||||
function);
|
||||
|
||||
/*
|
||||
* A device was found. Create a new device component for the
|
||||
* device and return its capability.
|
||||
@ -289,12 +294,25 @@ namespace Pci {
|
||||
|
||||
device->set_config_space(io_mem);
|
||||
|
||||
if (_child)
|
||||
_child->assign_pci(io_mem->dataspace());
|
||||
|
||||
return io_mem->dataspace();
|
||||
}
|
||||
|
||||
Genode::Ram_dataspace_capability alloc_dma_buffer(Device_capability device_cap,
|
||||
Genode::size_t size) {
|
||||
return Genode::env()->ram_session()->alloc(size, false); }
|
||||
Genode::size_t size)
|
||||
{
|
||||
Genode::Ram_dataspace_capability ram =
|
||||
Genode::env()->ram_session()->alloc(size, false);
|
||||
|
||||
if (!ram.valid() || !_child)
|
||||
return ram;
|
||||
|
||||
_child->attach_dma_mem(ram);
|
||||
|
||||
return ram;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -302,7 +320,8 @@ namespace Pci {
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Cap_session *_cap_session;
|
||||
/* for now we have only one device pd for all pci devices */
|
||||
Device_pd_client *_pd_device_client;
|
||||
|
||||
|
||||
void _parse_config()
|
||||
@ -340,7 +359,8 @@ namespace Pci {
|
||||
/* FIXME: extract quota from args */
|
||||
/* FIXME: pass quota to session-component constructor */
|
||||
|
||||
return new (md_alloc()) Session_component(ep(), md_alloc());
|
||||
return new (md_alloc()) Session_component(ep(), md_alloc(),
|
||||
_pd_device_client);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -353,13 +373,18 @@ namespace Pci {
|
||||
* \param md_alloc meta-data allocator for allocating PCI-session
|
||||
* components and PCI-device components
|
||||
*/
|
||||
Root(Genode::Rpc_entrypoint *ep,
|
||||
Genode::Allocator *md_alloc)
|
||||
Root(Genode::Rpc_entrypoint *ep, Genode::Allocator *md_alloc,
|
||||
Genode::size_t pci_device_pd_ram_quota,
|
||||
Genode::Capability <Device_pd> pci_device_pd)
|
||||
:
|
||||
Genode::Root_component<Session_component>(ep, md_alloc)
|
||||
Genode::Root_component<Session_component>(ep, md_alloc),
|
||||
_pd_device_client(0)
|
||||
{
|
||||
_parse_config();
|
||||
|
||||
if (pci_device_pd.valid())
|
||||
_pd_device_client = new (md_alloc) Device_pd_client(pci_device_pd);
|
||||
|
||||
/* enforce initial bus scan */
|
||||
bus_valid();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user