diff --git a/repos/os/include/pci_session/connection.h b/repos/os/include/pci_session/connection.h index e75a13b45..876faf30f 100644 --- a/repos/os/include/pci_session/connection.h +++ b/repos/os/include/pci_session/connection.h @@ -24,7 +24,7 @@ struct Pci::Connection : Genode::Connection, Session_client { Connection() : - Genode::Connection(session("ram_quota=4K")), + Genode::Connection(session("ram_quota=12K")), Session_client(cap()) { } }; diff --git a/repos/os/include/pci_session/pci_session.h b/repos/os/include/pci_session/pci_session.h index 3625f1c8a..e4c337710 100644 --- a/repos/os/include/pci_session/pci_session.h +++ b/repos/os/include/pci_session/pci_session.h @@ -86,16 +86,20 @@ struct Pci::Session : Genode::Session ** RPC declaration ** *********************/ - GENODE_RPC(Rpc_first_device, Device_capability, first_device, - unsigned, unsigned); - GENODE_RPC(Rpc_next_device, Device_capability, next_device, - Device_capability, unsigned, unsigned); + GENODE_RPC_THROW(Rpc_first_device, Device_capability, first_device, + GENODE_TYPE_LIST(Pci::Device::Quota_exceeded), + 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_config_extended, Genode::Io_mem_dataspace_capability, - config_extended, Device_capability); + GENODE_RPC_THROW(Rpc_config_extended, Genode::Io_mem_dataspace_capability, + config_extended, + GENODE_TYPE_LIST(Pci::Device::Quota_exceeded), + Device_capability); GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability, alloc_dma_buffer, - GENODE_TYPE_LIST(Genode::Ram_session::Quota_exceeded), + GENODE_TYPE_LIST(Pci::Device::Quota_exceeded), Genode::size_t); GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, Genode::Ram_dataspace_capability); diff --git a/repos/os/src/drivers/acpi/main.cc b/repos/os/src/drivers/acpi/main.cc index 51afef532..8c64a458b 100644 --- a/repos/os/src/drivers/acpi/main.cc +++ b/repos/os/src/drivers/acpi/main.cc @@ -147,7 +147,11 @@ namespace Pci { void close(Genode::Session_capability 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() { Pci::Session_capability session; - const char *args = "label=\"acpi_drv\", ram_quota=4K"; + const char *args = "label=\"acpi_drv\", ram_quota=16K"; try { using namespace Genode; diff --git a/repos/os/src/drivers/pci/pci_device_component.h b/repos/os/src/drivers/pci/pci_device_component.h index 749b64e7d..b13496904 100644 --- a/repos/os/src/drivers/pci/pci_device_component.h +++ b/repos/os/src/drivers/pci/pci_device_component.h @@ -114,7 +114,7 @@ class Pci::Device_component : public Genode::Rpc_object, { /* return invalid resource if device is invalid */ if (!_device_config.valid()) - Resource(0, 0); + return Resource(0, 0); return _device_config.resource(resource_id); } diff --git a/repos/os/src/drivers/pci/pci_device_config.h b/repos/os/src/drivers/pci/pci_device_config.h index b8b884f1e..c8b5efffe 100644 --- a/repos/os/src/drivers/pci/pci_device_config.h +++ b/repos/os/src/drivers/pci/pci_device_config.h @@ -56,6 +56,8 @@ namespace Pci { return resource_id >= 0 && resource_id < max_num; } + enum { INVALID_VENDOR = 0xffffU }; + public: enum { MAX_BUSES = 256, MAX_DEVICES = 32, MAX_FUNCTIONS = 8 }; @@ -63,7 +65,8 @@ namespace Pci { /** * Constructor */ - Device_config() { } + Device_config() : _vendor_id(INVALID_VENDOR) { } + Device_config(int bus, int device, int function, Config_access *pci_config): _bus(bus), _device(device), _function(function) @@ -71,7 +74,7 @@ namespace Pci { _vendor_id = pci_config->read(bus, device, function, 0, Device::ACCESS_16BIT); /* break here if device is invalid */ - if (_vendor_id == 0xffff) + if (_vendor_id == INVALID_VENDOR) return; _device_id = pci_config->read(bus, device, function, 2, Device::ACCESS_16BIT); @@ -88,7 +91,7 @@ namespace Pci { */ if (function != 0 && !(pci_config->read(bus, device, 0, 0xe, Device::ACCESS_8BIT) & 0x80)) { - _vendor_id = 0xffff; + _vendor_id = INVALID_VENDOR; return; } @@ -152,7 +155,7 @@ namespace Pci { /** * 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 diff --git a/repos/os/src/drivers/pci/pci_session_component.h b/repos/os/src/drivers/pci/pci_session_component.h index 08225f276..844ba8d78 100644 --- a/repos/os/src/drivers/pci/pci_session_component.h +++ b/repos/os/src/drivers/pci/pci_session_component.h @@ -15,7 +15,10 @@ #define _PCI_SESSION_COMPONENT_H_ /* base */ +#include #include +#include + #include #include @@ -40,13 +43,14 @@ namespace Pci { { private: - Genode::Rpc_entrypoint *_ep; - Genode::Allocator *_md_alloc; - Genode::List _device_list; - Device_pd_client *_child; - Genode::Ram_connection *_ram; - Genode::Session_label _label; - Genode::Session_policy _policy; + Genode::Rpc_entrypoint *_ep; + Genode::Allocator_guard _md_alloc; + Genode::Tslab _device_slab; + Genode::List _device_list; + Device_pd_client *_child; + Genode::Ram_connection *_ram; + Genode::Session_label _label; + Genode::Session_policy _policy; /** * Scan PCI buses for a device @@ -296,7 +300,9 @@ namespace Pci { Genode::Ram_connection *ram, 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) { /* non-pci devices */ @@ -403,6 +409,10 @@ namespace Pci { 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, Genode::uint32_t func_count, Genode::addr_t base) @@ -484,17 +494,14 @@ namespace Pci { /* * A device was found. Create a new device component for the * device and return its capability. - * - * FIXME: check and adjust session quota */ - Device_component *device_component = - new (_md_alloc) Device_component(config, config_space, _ep, this); - - if (!device_component) - return Device_capability(); - - _device_list.insert(device_component); - return _ep->manage(device_component); + try { + Device_component * dev = new (_device_slab) Device_component(config, config_space, _ep, this); + _device_list.insert(dev); + return _ep->manage(dev); + } catch (Genode::Allocator::Out_of_memory) { + throw Device::Quota_exceeded(); + } } void release_device(Device_capability device_cap) @@ -509,11 +516,14 @@ namespace Pci { _device_list.remove(device); _ep->dissolve(device); - /* FIXME: adjust quota */ Genode::Io_mem_connection * io_mem = device->get_config_space(); if (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) @@ -533,6 +543,8 @@ namespace Pci { try { io_mem = new (_md_alloc) Io_mem_connection(device->config_space(), 0x1000); + } catch (Genode::Allocator::Out_of_memory) { + throw Device::Quota_exceeded(); } catch (Parent::Service_denied) { return Io_mem_dataspace_capability(); } @@ -552,17 +564,30 @@ namespace Pci { Ram_capability alloc_dma_buffer(Genode::size_t size) { - if (Genode::env()->ram_session()->transfer_quota(_ram->cap(), - size)) + if (!_md_alloc.withdraw(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(); + } - Ram_capability ram = _ram->alloc(size, Genode::UNCACHED); - if (!ram.valid() || !_child) - return ram; + Ram_capability ram_cap; + try { - _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) @@ -623,9 +648,6 @@ namespace Pci { Session_component *_create_session(const char *args) { - /* FIXME: extract quota from args */ - /* FIXME: pass quota to session-component constructor */ - try { return new (md_alloc()) Session_component(ep(), md_alloc(), _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: /** @@ -653,7 +683,6 @@ namespace Pci { : Genode::Root_component(ep, md_alloc), _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 */ _ram("dma", 0, (pci_device_pd.valid() && sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000ULL) @@ -661,7 +690,7 @@ namespace Pci { _parse_config(); 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 */ _ram.ref_account(Genode::env()->ram_session_cap());