x86: extend io_mem call of platform_drv

Support allocation of sub I/O memory spaces of one I/O memory bar with
write-combined caching attribute.
This commit is contained in:
Alexander Boettcher 2015-09-09 11:06:36 +02:00 committed by Christian Helmuth
parent 8f849c9438
commit bdaf79e3b8
7 changed files with 74 additions and 29 deletions

View File

@ -14,6 +14,7 @@
#ifndef _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
#define _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
#include <base/cache.h>
#include <irq_session/capability.h>
#include <io_mem_session/capability.h>
@ -29,7 +30,9 @@ struct Platform::Abstract_device
/**
* Get IO mem session capability of specified resource id
*/
virtual Genode::Io_mem_session_capability io_mem(Genode::uint8_t) = 0;
virtual Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) = 0;
};
#endif /* _INCLUDE__PLATFORM_DEVICE__DEVICE_H_ */

View File

@ -54,8 +54,11 @@ struct Platform::Device_client : public Genode::Rpc_client<Device>
Genode::Io_port_session_capability io_port(Genode::uint8_t id) override {
return call<Rpc_io_port>(id); }
Genode::Io_mem_session_capability io_mem(Genode::uint8_t id) override {
return call<Rpc_io_mem>(id); }
Genode::Io_mem_session_capability io_mem(Genode::uint8_t id,
Genode::Cache_attribute caching = Genode::Cache_attribute::UNCACHED,
Genode::addr_t offset = 0,
Genode::size_t size = ~0UL) override {
return call<Rpc_io_mem>(id, caching, offset, size); }
};
#endif /* _INCLUDE__SPEC__X86__PLATFORM_DEVICE__CLIENT_H_ */

View File

@ -242,7 +242,8 @@ struct Platform::Device : Platform::Abstract_device
Genode::uint8_t);
GENODE_RPC_THROW(Rpc_io_mem, Genode::Io_mem_session_capability, io_mem,
GENODE_TYPE_LIST(Quota_exceeded),
Genode::uint8_t);
Genode::uint8_t, Genode::Cache_attribute,
Genode::addr_t, Genode::size_t);
typedef Genode::Meta::Type_tuple<Rpc_bus_address,
Genode::Meta::Type_tuple<Rpc_vendor_id,

View File

@ -66,7 +66,10 @@ class Nonpci::Ps2 : public Platform::Device_component
return Genode::Io_port_session_capability();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t) override
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t,
Genode::size_t) override
{
return Genode::Io_mem_session_capability();
}

View File

@ -28,18 +28,26 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u
continue;
}
if (_io_port_conn[v_id] == nullptr)
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size());
if (_io_port_conn[v_id] != nullptr)
return _io_port_conn[v_id]->cap();
return _io_port_conn[v_id]->cap();
try {
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size());
return _io_port_conn[v_id]->cap();
} catch (...) {
return Genode::Io_port_session_capability();
}
}
return Genode::Io_port_session_capability();
}
Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uint8_t v_id)
Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uint8_t const v_id,
Genode::Cache_attribute const caching,
Genode::addr_t const offset,
Genode::size_t const size)
{
Genode::uint8_t max = sizeof(_io_mem_conn) / sizeof(_io_mem_conn[0]);
Genode::uint8_t max = sizeof(_io_mem) / sizeof(_io_mem[0]);
Genode::uint8_t i = 0, r_id = 0;
for (Resource res = resource(0); i < max; i++, res = resource(i))
@ -52,17 +60,31 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin
continue;
}
if (_io_mem_conn[v_id] == nullptr)
_io_mem_conn[v_id] = new (_slab_iomem) Genode::Io_mem_connection(res.base(), res.size());
/* limit IO_MEM session size to resource size */
Genode::size_t const res_size = Genode::min(size, res.size());
return _io_mem_conn[v_id]->cap();
if (offset >= res.size() || offset > res.size() - res_size)
return Genode::Io_mem_session_capability();
try {
bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED;
Io_mem * io_mem = new (_slab_iomem) Io_mem(res.base() + offset,
res_size, wc);
_io_mem[i].insert(io_mem);
return io_mem->cap();
} catch (Genode::Allocator::Out_of_memory) {
throw Platform::Device::Quota_exceeded();
} catch (...) {
return Genode::Io_mem_session_capability();
}
}
return Genode::Io_mem_session_capability();
}
void Platform::Device_component::config_write(unsigned char address, unsigned value,
Access_size size)
void Platform::Device_component::config_write(unsigned char address,
unsigned value,
Access_size size)
{
/* white list of ports which we permit to write */
switch (address) {
@ -99,4 +121,3 @@ void Platform::Device_component::config_write(unsigned char address, unsigned va
_device_config.write(&_config_access, address, value, size,
_device_config.DONT_TRACK_ACCESS);
}

View File

@ -42,9 +42,19 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
unsigned short _irq_line;
Irq_session_component _irq_session;
class Io_mem : public Genode::Io_mem_connection,
public Genode::List<Io_mem>::Element
{
public:
Io_mem (Genode::addr_t base, Genode::size_t size, bool wc)
: Genode::Io_mem_connection(base, size, wc) { }
};
enum {
IO_BLOCK_SIZE = sizeof(Genode::Io_port_connection) *
Device::NUM_RESOURCES + 32 + 8 * sizeof(void *),
IO_MEM_SIZE = sizeof(Io_mem) *
Device::NUM_RESOURCES + 32 + 8 * sizeof(void *),
PCI_CMD_REG = 0x4,
PCI_CMD_DMA = 0x4,
PCI_IRQ_LINE = 0x3c,
@ -58,12 +68,12 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
Genode::Slab_block _slab_ioport_block;
char _slab_ioport_block_data[IO_BLOCK_SIZE];
Genode::Tslab<Genode::Io_mem_connection, IO_BLOCK_SIZE> _slab_iomem;
Genode::Tslab<Io_mem, IO_MEM_SIZE> _slab_iomem;
Genode::Slab_block _slab_iomem_block;
char _slab_iomem_block_data[IO_BLOCK_SIZE];
char _slab_iomem_block_data[IO_MEM_SIZE];
Genode::Io_port_connection *_io_port_conn [Device::NUM_RESOURCES];
Genode::Io_mem_connection *_io_mem_conn [Device::NUM_RESOURCES];
Genode::List<Io_mem> _io_mem [Device::NUM_RESOURCES];
struct Status : Genode::Register<8> {
struct Capabilities : Bitfield<4,1> { };
@ -179,6 +189,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
Device_component(Device_config device_config, Genode::addr_t addr,
Genode::Rpc_entrypoint *ep,
Platform::Session_component * session,
Genode::Allocator * md_alloc,
bool use_msi)
:
_device_config(device_config), _config_space(addr),
@ -186,8 +197,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
Platform::Device::ACCESS_8BIT)),
_irq_session(_configure_irq(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
_slab_ioport(0, &_slab_ioport_block),
_slab_iomem(0, &_slab_iomem_block)
_slab_ioport(md_alloc, &_slab_ioport_block),
_slab_iomem(md_alloc, &_slab_iomem_block)
{
if (_config_space != ~0UL) {
try {
@ -201,7 +212,6 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
_io_port_conn[i] = nullptr;
_io_mem_conn[i] = nullptr;
}
if (_slab_ioport.num_elem() != Device::NUM_RESOURCES)
@ -262,10 +272,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
{
_ep->manage(&_irq_session);
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++)
_io_port_conn[i] = nullptr;
_io_mem_conn[i] = nullptr;
}
}
/**
@ -278,8 +286,11 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
if (_io_port_conn[i])
Genode::destroy(_slab_ioport, _io_port_conn[i]);
if (_io_mem_conn[i])
Genode::destroy(_slab_iomem, _io_mem_conn[i]);
while (Io_mem * io_mem = _io_mem[i].first()) {
_io_mem[i].remove(io_mem);
Genode::destroy(_slab_iomem, io_mem);
}
}
if (_io_mem_config_extended.valid())
@ -377,5 +388,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
Genode::Io_port_session_capability io_port(Genode::uint8_t) override;
Genode::Io_mem_session_capability io_mem(Genode::uint8_t) override;
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t,
Genode::size_t) override;
};

View File

@ -535,7 +535,7 @@ namespace Platform {
try {
Device_component * dev = new (_device_slab)
Device_component(config, config_space, _ep, this,
msi_usage());
&_md_alloc, msi_usage());
/* if more than one driver uses the device - warn about */
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +