mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 10:01:57 +00:00
parent
df50d1b29d
commit
06e7c947bc
@ -24,7 +24,7 @@ struct Pci::Connection : Genode::Connection<Session>, Session_client
|
|||||||
{
|
{
|
||||||
Connection()
|
Connection()
|
||||||
:
|
:
|
||||||
Genode::Connection<Session>(session("ram_quota=4K")),
|
Genode::Connection<Session>(session("ram_quota=12K")),
|
||||||
Session_client(cap())
|
Session_client(cap())
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -86,16 +86,20 @@ struct Pci::Session : Genode::Session
|
|||||||
** RPC declaration **
|
** RPC declaration **
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
GENODE_RPC(Rpc_first_device, Device_capability, first_device,
|
GENODE_RPC_THROW(Rpc_first_device, Device_capability, first_device,
|
||||||
unsigned, unsigned);
|
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||||
GENODE_RPC(Rpc_next_device, Device_capability, next_device,
|
unsigned, unsigned);
|
||||||
Device_capability, unsigned, unsigned);
|
GENODE_RPC_THROW(Rpc_next_device, Device_capability, next_device,
|
||||||
|
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||||
|
Device_capability, unsigned, unsigned);
|
||||||
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
||||||
GENODE_RPC(Rpc_config_extended, Genode::Io_mem_dataspace_capability,
|
GENODE_RPC_THROW(Rpc_config_extended, Genode::Io_mem_dataspace_capability,
|
||||||
config_extended, Device_capability);
|
config_extended,
|
||||||
|
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||||
|
Device_capability);
|
||||||
GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability,
|
GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability,
|
||||||
alloc_dma_buffer,
|
alloc_dma_buffer,
|
||||||
GENODE_TYPE_LIST(Genode::Ram_session::Quota_exceeded),
|
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||||
Genode::size_t);
|
Genode::size_t);
|
||||||
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
||||||
Genode::Ram_dataspace_capability);
|
Genode::Ram_dataspace_capability);
|
||||||
|
@ -147,7 +147,11 @@ namespace Pci {
|
|||||||
void close(Genode::Session_capability session) {
|
void close(Genode::Session_capability session) {
|
||||||
Genode::Root_client(_pci_provider.root()).close(session); }
|
Genode::Root_client(_pci_provider.root()).close(session); }
|
||||||
|
|
||||||
void upgrade(Genode::Session_capability, Upgrade_args const &) { }
|
void upgrade(Genode::Session_capability s, Upgrade_args const & u)
|
||||||
|
{
|
||||||
|
try { Genode::Root_client(_pci_provider.root()).upgrade(s, u); }
|
||||||
|
catch (...) { throw Invalid_args(); }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +182,7 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
|||||||
void _acpi_session()
|
void _acpi_session()
|
||||||
{
|
{
|
||||||
Pci::Session_capability session;
|
Pci::Session_capability session;
|
||||||
const char *args = "label=\"acpi_drv\", ram_quota=4K";
|
const char *args = "label=\"acpi_drv\", ram_quota=16K";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
@ -114,7 +114,7 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
|
|||||||
{
|
{
|
||||||
/* return invalid resource if device is invalid */
|
/* return invalid resource if device is invalid */
|
||||||
if (!_device_config.valid())
|
if (!_device_config.valid())
|
||||||
Resource(0, 0);
|
return Resource(0, 0);
|
||||||
|
|
||||||
return _device_config.resource(resource_id);
|
return _device_config.resource(resource_id);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,8 @@ namespace Pci {
|
|||||||
return resource_id >= 0 && resource_id < max_num;
|
return resource_id >= 0 && resource_id < max_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum { INVALID_VENDOR = 0xffffU };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum { MAX_BUSES = 256, MAX_DEVICES = 32, MAX_FUNCTIONS = 8 };
|
enum { MAX_BUSES = 256, MAX_DEVICES = 32, MAX_FUNCTIONS = 8 };
|
||||||
@ -63,7 +65,8 @@ namespace Pci {
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Device_config() { }
|
Device_config() : _vendor_id(INVALID_VENDOR) { }
|
||||||
|
|
||||||
Device_config(int bus, int device, int function,
|
Device_config(int bus, int device, int function,
|
||||||
Config_access *pci_config):
|
Config_access *pci_config):
|
||||||
_bus(bus), _device(device), _function(function)
|
_bus(bus), _device(device), _function(function)
|
||||||
@ -71,7 +74,7 @@ namespace Pci {
|
|||||||
_vendor_id = pci_config->read(bus, device, function, 0, Device::ACCESS_16BIT);
|
_vendor_id = pci_config->read(bus, device, function, 0, Device::ACCESS_16BIT);
|
||||||
|
|
||||||
/* break here if device is invalid */
|
/* break here if device is invalid */
|
||||||
if (_vendor_id == 0xffff)
|
if (_vendor_id == INVALID_VENDOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_device_id = pci_config->read(bus, device, function, 2, Device::ACCESS_16BIT);
|
_device_id = pci_config->read(bus, device, function, 2, Device::ACCESS_16BIT);
|
||||||
@ -88,7 +91,7 @@ namespace Pci {
|
|||||||
*/
|
*/
|
||||||
if (function != 0
|
if (function != 0
|
||||||
&& !(pci_config->read(bus, device, 0, 0xe, Device::ACCESS_8BIT) & 0x80)) {
|
&& !(pci_config->read(bus, device, 0, 0xe, Device::ACCESS_8BIT) & 0x80)) {
|
||||||
_vendor_id = 0xffff;
|
_vendor_id = INVALID_VENDOR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +155,7 @@ namespace Pci {
|
|||||||
/**
|
/**
|
||||||
* Return true if device is valid
|
* Return true if device is valid
|
||||||
*/
|
*/
|
||||||
bool valid() { return _vendor_id != 0xffff; }
|
bool valid() { return _vendor_id != INVALID_VENDOR; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return resource description by resource ID
|
* Return resource description by resource ID
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
#define _PCI_SESSION_COMPONENT_H_
|
#define _PCI_SESSION_COMPONENT_H_
|
||||||
|
|
||||||
/* base */
|
/* base */
|
||||||
|
#include <base/allocator_guard.h>
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
|
#include <base/tslab.h>
|
||||||
|
|
||||||
#include <ram_session/connection.h>
|
#include <ram_session/connection.h>
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
|
|
||||||
@ -40,13 +43,14 @@ namespace Pci {
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Rpc_entrypoint *_ep;
|
Genode::Rpc_entrypoint *_ep;
|
||||||
Genode::Allocator *_md_alloc;
|
Genode::Allocator_guard _md_alloc;
|
||||||
Genode::List<Device_component> _device_list;
|
Genode::Tslab<Device_component, 4096 - 64> _device_slab;
|
||||||
Device_pd_client *_child;
|
Genode::List<Device_component> _device_list;
|
||||||
Genode::Ram_connection *_ram;
|
Device_pd_client *_child;
|
||||||
Genode::Session_label _label;
|
Genode::Ram_connection *_ram;
|
||||||
Genode::Session_policy _policy;
|
Genode::Session_label _label;
|
||||||
|
Genode::Session_policy _policy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan PCI buses for a device
|
* Scan PCI buses for a device
|
||||||
@ -296,7 +300,9 @@ namespace Pci {
|
|||||||
Genode::Ram_connection *ram,
|
Genode::Ram_connection *ram,
|
||||||
const char *args)
|
const char *args)
|
||||||
:
|
:
|
||||||
_ep(ep), _md_alloc(md_alloc),
|
_ep(ep),
|
||||||
|
_md_alloc(md_alloc, Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
|
||||||
|
_device_slab(&_md_alloc),
|
||||||
_child(child), _ram(ram), _label(args), _policy(_label)
|
_child(child), _ram(ram), _label(args), _policy(_label)
|
||||||
{
|
{
|
||||||
/* non-pci devices */
|
/* non-pci devices */
|
||||||
@ -403,6 +409,10 @@ namespace Pci {
|
|||||||
release_device(_device_list.first()->cap());
|
release_device(_device_list.first()->cap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void upgrade_ram_quota(long quota) { _md_alloc.upgrade(quota); }
|
||||||
|
|
||||||
|
|
||||||
static void add_config_space(Genode::uint32_t bdf_start,
|
static void add_config_space(Genode::uint32_t bdf_start,
|
||||||
Genode::uint32_t func_count,
|
Genode::uint32_t func_count,
|
||||||
Genode::addr_t base)
|
Genode::addr_t base)
|
||||||
@ -484,17 +494,14 @@ namespace Pci {
|
|||||||
/*
|
/*
|
||||||
* A device was found. Create a new device component for the
|
* A device was found. Create a new device component for the
|
||||||
* device and return its capability.
|
* device and return its capability.
|
||||||
*
|
|
||||||
* FIXME: check and adjust session quota
|
|
||||||
*/
|
*/
|
||||||
Device_component *device_component =
|
try {
|
||||||
new (_md_alloc) Device_component(config, config_space, _ep, this);
|
Device_component * dev = new (_device_slab) Device_component(config, config_space, _ep, this);
|
||||||
|
_device_list.insert(dev);
|
||||||
if (!device_component)
|
return _ep->manage(dev);
|
||||||
return Device_capability();
|
} catch (Genode::Allocator::Out_of_memory) {
|
||||||
|
throw Device::Quota_exceeded();
|
||||||
_device_list.insert(device_component);
|
}
|
||||||
return _ep->manage(device_component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_device(Device_capability device_cap)
|
void release_device(Device_capability device_cap)
|
||||||
@ -509,11 +516,14 @@ namespace Pci {
|
|||||||
_device_list.remove(device);
|
_device_list.remove(device);
|
||||||
_ep->dissolve(device);
|
_ep->dissolve(device);
|
||||||
|
|
||||||
/* FIXME: adjust quota */
|
|
||||||
Genode::Io_mem_connection * io_mem = device->get_config_space();
|
Genode::Io_mem_connection * io_mem = device->get_config_space();
|
||||||
if (io_mem)
|
if (io_mem)
|
||||||
destroy(_md_alloc, io_mem);
|
destroy(_md_alloc, io_mem);
|
||||||
destroy(_md_alloc, device);
|
|
||||||
|
if (device->config().valid())
|
||||||
|
destroy(_device_slab, device);
|
||||||
|
else
|
||||||
|
destroy(_md_alloc, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap)
|
Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap)
|
||||||
@ -533,6 +543,8 @@ namespace Pci {
|
|||||||
try {
|
try {
|
||||||
io_mem = new (_md_alloc) Io_mem_connection(device->config_space(),
|
io_mem = new (_md_alloc) Io_mem_connection(device->config_space(),
|
||||||
0x1000);
|
0x1000);
|
||||||
|
} catch (Genode::Allocator::Out_of_memory) {
|
||||||
|
throw Device::Quota_exceeded();
|
||||||
} catch (Parent::Service_denied) {
|
} catch (Parent::Service_denied) {
|
||||||
return Io_mem_dataspace_capability();
|
return Io_mem_dataspace_capability();
|
||||||
}
|
}
|
||||||
@ -552,17 +564,30 @@ namespace Pci {
|
|||||||
|
|
||||||
Ram_capability alloc_dma_buffer(Genode::size_t size)
|
Ram_capability alloc_dma_buffer(Genode::size_t size)
|
||||||
{
|
{
|
||||||
if (Genode::env()->ram_session()->transfer_quota(_ram->cap(),
|
if (!_md_alloc.withdraw(size))
|
||||||
size))
|
throw Device::Quota_exceeded();
|
||||||
|
|
||||||
|
Genode::Ram_session * const rs = Genode::env()->ram_session();
|
||||||
|
if (rs->transfer_quota(_ram->cap(), size)) {
|
||||||
|
_md_alloc.upgrade(size);
|
||||||
return Ram_capability();
|
return Ram_capability();
|
||||||
|
}
|
||||||
|
|
||||||
Ram_capability ram = _ram->alloc(size, Genode::UNCACHED);
|
Ram_capability ram_cap;
|
||||||
if (!ram.valid() || !_child)
|
try {
|
||||||
return ram;
|
|
||||||
|
|
||||||
_child->attach_dma_mem(ram);
|
ram_cap = _ram->alloc(size, Genode::UNCACHED);
|
||||||
|
} catch (Genode::Ram_session::Quota_exceeded) {
|
||||||
|
_md_alloc.upgrade(size);
|
||||||
|
return Ram_capability();
|
||||||
|
}
|
||||||
|
|
||||||
return ram;
|
if (!ram_cap.valid() || !_child)
|
||||||
|
return ram_cap;
|
||||||
|
|
||||||
|
_child->attach_dma_mem(ram_cap);
|
||||||
|
|
||||||
|
return ram_cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_dma_buffer(Ram_capability ram)
|
void free_dma_buffer(Ram_capability ram)
|
||||||
@ -623,9 +648,6 @@ namespace Pci {
|
|||||||
|
|
||||||
Session_component *_create_session(const char *args)
|
Session_component *_create_session(const char *args)
|
||||||
{
|
{
|
||||||
/* FIXME: extract quota from args */
|
|
||||||
/* FIXME: pass quota to session-component constructor */
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new (md_alloc()) Session_component(ep(), md_alloc(),
|
return new (md_alloc()) Session_component(ep(), md_alloc(),
|
||||||
_pd_device_client,
|
_pd_device_client,
|
||||||
@ -637,6 +659,14 @@ namespace Pci {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _upgrade_session(Session_component *s, const char *args) override
|
||||||
|
{
|
||||||
|
long ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").long_value(0);
|
||||||
|
s->upgrade_ram_quota(ram_quota);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -653,7 +683,6 @@ namespace Pci {
|
|||||||
:
|
:
|
||||||
Genode::Root_component<Session_component>(ep, md_alloc),
|
Genode::Root_component<Session_component>(ep, md_alloc),
|
||||||
_pd_device_client(0),
|
_pd_device_client(0),
|
||||||
/* restrict physical address to 4G on 32/64bit in general XXX */
|
|
||||||
/* restrict physical address to 3G on 32bit with device_pd */
|
/* restrict physical address to 3G on 32bit with device_pd */
|
||||||
_ram("dma", 0, (pci_device_pd.valid() && sizeof(void *) == 4) ?
|
_ram("dma", 0, (pci_device_pd.valid() && sizeof(void *) == 4) ?
|
||||||
0xc0000000UL : 0x100000000ULL)
|
0xc0000000UL : 0x100000000ULL)
|
||||||
@ -661,7 +690,7 @@ namespace Pci {
|
|||||||
_parse_config();
|
_parse_config();
|
||||||
|
|
||||||
if (pci_device_pd.valid())
|
if (pci_device_pd.valid())
|
||||||
_pd_device_client = new (md_alloc) Device_pd_client(pci_device_pd);
|
_pd_device_client = new (Genode::env()->heap()) Device_pd_client(pci_device_pd);
|
||||||
|
|
||||||
/* associate _ram session with ram_session of process */
|
/* associate _ram session with ram_session of process */
|
||||||
_ram.ref_account(Genode::env()->ram_session_cap());
|
_ram.ref_account(Genode::env()->ram_session_cap());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user