mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-01 16:58:29 +00:00
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:
parent
8f849c9438
commit
bdaf79e3b8
@ -14,6 +14,7 @@
|
|||||||
#ifndef _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
|
#ifndef _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
|
||||||
#define _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
|
#define _INCLUDE__PLATFORM_DEVICE__DEVICE_H_
|
||||||
|
|
||||||
|
#include <base/cache.h>
|
||||||
#include <irq_session/capability.h>
|
#include <irq_session/capability.h>
|
||||||
#include <io_mem_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
|
* 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_ */
|
#endif /* _INCLUDE__PLATFORM_DEVICE__DEVICE_H_ */
|
||||||
|
@ -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 {
|
Genode::Io_port_session_capability io_port(Genode::uint8_t id) override {
|
||||||
return call<Rpc_io_port>(id); }
|
return call<Rpc_io_port>(id); }
|
||||||
|
|
||||||
Genode::Io_mem_session_capability io_mem(Genode::uint8_t id) override {
|
Genode::Io_mem_session_capability io_mem(Genode::uint8_t id,
|
||||||
return call<Rpc_io_mem>(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_ */
|
#endif /* _INCLUDE__SPEC__X86__PLATFORM_DEVICE__CLIENT_H_ */
|
||||||
|
@ -242,7 +242,8 @@ struct Platform::Device : Platform::Abstract_device
|
|||||||
Genode::uint8_t);
|
Genode::uint8_t);
|
||||||
GENODE_RPC_THROW(Rpc_io_mem, Genode::Io_mem_session_capability, io_mem,
|
GENODE_RPC_THROW(Rpc_io_mem, Genode::Io_mem_session_capability, io_mem,
|
||||||
GENODE_TYPE_LIST(Quota_exceeded),
|
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,
|
typedef Genode::Meta::Type_tuple<Rpc_bus_address,
|
||||||
Genode::Meta::Type_tuple<Rpc_vendor_id,
|
Genode::Meta::Type_tuple<Rpc_vendor_id,
|
||||||
|
@ -66,7 +66,10 @@ class Nonpci::Ps2 : public Platform::Device_component
|
|||||||
return Genode::Io_port_session_capability();
|
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();
|
return Genode::Io_mem_session_capability();
|
||||||
}
|
}
|
||||||
|
@ -28,18 +28,26 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_io_port_conn[v_id] == nullptr)
|
if (_io_port_conn[v_id] != nullptr)
|
||||||
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size());
|
|
||||||
|
|
||||||
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();
|
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;
|
Genode::uint8_t i = 0, r_id = 0;
|
||||||
|
|
||||||
for (Resource res = resource(0); i < max; i++, res = resource(i))
|
for (Resource res = resource(0); i < max; i++, res = resource(i))
|
||||||
@ -52,16 +60,30 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_io_mem_conn[v_id] == nullptr)
|
/* limit IO_MEM session size to resource size */
|
||||||
_io_mem_conn[v_id] = new (_slab_iomem) Genode::Io_mem_connection(res.base(), res.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();
|
return Genode::Io_mem_session_capability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Platform::Device_component::config_write(unsigned char address, unsigned value,
|
void Platform::Device_component::config_write(unsigned char address,
|
||||||
|
unsigned value,
|
||||||
Access_size size)
|
Access_size size)
|
||||||
{
|
{
|
||||||
/* white list of ports which we permit to write */
|
/* white list of ports which we permit to write */
|
||||||
@ -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.write(&_config_access, address, value, size,
|
||||||
_device_config.DONT_TRACK_ACCESS);
|
_device_config.DONT_TRACK_ACCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,9 +42,19 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
unsigned short _irq_line;
|
unsigned short _irq_line;
|
||||||
Irq_session_component _irq_session;
|
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 {
|
enum {
|
||||||
IO_BLOCK_SIZE = sizeof(Genode::Io_port_connection) *
|
IO_BLOCK_SIZE = sizeof(Genode::Io_port_connection) *
|
||||||
Device::NUM_RESOURCES + 32 + 8 * sizeof(void *),
|
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_REG = 0x4,
|
||||||
PCI_CMD_DMA = 0x4,
|
PCI_CMD_DMA = 0x4,
|
||||||
PCI_IRQ_LINE = 0x3c,
|
PCI_IRQ_LINE = 0x3c,
|
||||||
@ -58,12 +68,12 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
Genode::Slab_block _slab_ioport_block;
|
Genode::Slab_block _slab_ioport_block;
|
||||||
char _slab_ioport_block_data[IO_BLOCK_SIZE];
|
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;
|
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_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 Status : Genode::Register<8> {
|
||||||
struct Capabilities : Bitfield<4,1> { };
|
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,
|
Device_component(Device_config device_config, Genode::addr_t addr,
|
||||||
Genode::Rpc_entrypoint *ep,
|
Genode::Rpc_entrypoint *ep,
|
||||||
Platform::Session_component * session,
|
Platform::Session_component * session,
|
||||||
|
Genode::Allocator * md_alloc,
|
||||||
bool use_msi)
|
bool use_msi)
|
||||||
:
|
:
|
||||||
_device_config(device_config), _config_space(addr),
|
_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,
|
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
||||||
Platform::Device::ACCESS_8BIT)),
|
Platform::Device::ACCESS_8BIT)),
|
||||||
_irq_session(_configure_irq(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
|
_irq_session(_configure_irq(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
|
||||||
_slab_ioport(0, &_slab_ioport_block),
|
_slab_ioport(md_alloc, &_slab_ioport_block),
|
||||||
_slab_iomem(0, &_slab_iomem_block)
|
_slab_iomem(md_alloc, &_slab_iomem_block)
|
||||||
{
|
{
|
||||||
if (_config_space != ~0UL) {
|
if (_config_space != ~0UL) {
|
||||||
try {
|
try {
|
||||||
@ -201,7 +212,6 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
|
|
||||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||||
_io_port_conn[i] = nullptr;
|
_io_port_conn[i] = nullptr;
|
||||||
_io_mem_conn[i] = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_slab_ioport.num_elem() != Device::NUM_RESOURCES)
|
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);
|
_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_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++) {
|
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||||
if (_io_port_conn[i])
|
if (_io_port_conn[i])
|
||||||
Genode::destroy(_slab_ioport, _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())
|
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_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;
|
||||||
};
|
};
|
||||||
|
@ -535,7 +535,7 @@ namespace Platform {
|
|||||||
try {
|
try {
|
||||||
Device_component * dev = new (_device_slab)
|
Device_component * dev = new (_device_slab)
|
||||||
Device_component(config, config_space, _ep, this,
|
Device_component(config, config_space, _ep, this,
|
||||||
msi_usage());
|
&_md_alloc, msi_usage());
|
||||||
|
|
||||||
/* if more than one driver uses the device - warn about */
|
/* if more than one driver uses the device - warn about */
|
||||||
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
||||||
|
Loading…
x
Reference in New Issue
Block a user