platform_drv: export Intel graphics PCI infos

Provide additional PCI register information inside the pci-config part
of the devices ROM for clients able to access an Intel graphic card,
namely the GMCH control register content, which contains for instance
the GTT size and stolen memory size.

Ref genodelabs/genode#4578
This commit is contained in:
Stefan Kalkowski 2022-07-27 17:30:17 +02:00 committed by Christian Helmuth
parent 9dfc2caa11
commit 8255053242
11 changed files with 165 additions and 19 deletions

View File

@ -24,7 +24,7 @@ class Driver::Common : Device_reporter
Attached_rom_dataspace _devices_rom { _env, _rom_name.string() };
Heap _heap { _env.ram(), _env.rm() };
Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
Device_model _devices { _heap, *this };
Device_model _devices { _env, _heap, *this };
Signal_handler<Common> _dev_handler { _env.ep(), *this,
&Common::_handle_devices };
Driver::Root _root;

View File

@ -79,7 +79,7 @@ void Driver::Device::acquire(Session_component & sc)
}
});
pci_enable(sc.env(), sc.device_pd(), *this);
pci_enable(_env, sc.device_pd(), *this);
sc.update_devices_rom();
_model.device_status_changed();
}
@ -90,7 +90,7 @@ void Driver::Device::release(Session_component & sc)
if (!(_owner == sc))
return;
pci_disable(sc.env(), *this);
pci_disable(_env, *this);
_reset_domain_list.for_each([&] (Reset_domain & r)
{
@ -171,14 +171,15 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const
xml.attribute("revision", String<16>(Hex(pci.revision)));
xml.attribute("sub_vendor_id", String<16>(Hex(pci.sub_vendor_id)));
xml.attribute("sub_device_id", String<16>(Hex(pci.sub_device_id)));
pci_device_specific_info(*this, _env, _model, xml);
});
});
});
}
Driver::Device::Device(Device_model & model, Name name, Type type)
: _model(model), _name(name), _type(type) { }
Driver::Device::Device(Env & env, Device_model & model, Name name, Type type)
: _env(env), _model(model), _name(name), _type(type) { }
Driver::Device::~Device()

View File

@ -197,7 +197,7 @@ class Driver::Device : private List_model<Device>::Element
bridge(bridge) {}
};
Device(Device_model & model, Name name, Type type);
Device(Env & env, Device_model & model, Name name, Type type);
virtual ~Device();
Name name() const;
@ -253,6 +253,7 @@ class Driver::Device : private List_model<Device>::Element
friend class List_model<Device>;
friend class List<Device>;
Env & _env;
Device_model & _model;
Name const _name;
Type const _type;
@ -287,6 +288,7 @@ class Driver::Device_model :
{
private:
Env & _env;
Heap & _heap;
Device_reporter & _reporter;
List_model<Device> _model { };
@ -300,9 +302,10 @@ class Driver::Device_model :
void update(Xml_node const & node);
void device_status_changed();
Device_model(Heap & heap,
Device_model(Env & env,
Heap & heap,
Device_reporter & reporter)
: _heap(heap), _reporter(reporter) { }
: _env(env), _heap(heap), _reporter(reporter) { }
~Device_model() {
_model.destroy_all_elements(*this); }

View File

@ -49,7 +49,7 @@ Device_component::io_mem(unsigned idx, Range &range, Cache cache)
return;
if (!iomem.io_mem.constructed())
iomem.io_mem.construct(_session.env(),
iomem.io_mem.construct(_env,
iomem.range.start,
iomem.range.size,
cache == WRITE_COMBINED);
@ -79,11 +79,11 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx)
else
error("MSI(-x) detected for device without pci-config!");
}
irq.irq.construct(_session.env(), irq.number, irq.mode, irq.polarity,
irq.irq.construct(_env, irq.number, irq.mode, irq.polarity,
pci_cfg_addr);
Irq_session::Info info = irq.irq->info();
if (info.type == Irq_session::Info::MSI)
pci_msi_enable(_session.env(), pci_cfg_addr, info);
pci_msi_enable(_env, pci_cfg_addr, info);
}
cap = irq.irq->cap();
@ -103,7 +103,7 @@ Genode::Io_port_session_capability Device_component::io_port_range(unsigned idx)
return;
if (!ipr.io_port_range.constructed())
ipr.io_port_range.construct(_session.env(), ipr.range.addr,
ipr.io_port_range.construct(_env, ipr.range.addr,
ipr.range.size);
cap = ipr.io_port_range->cap();
@ -114,9 +114,14 @@ Genode::Io_port_session_capability Device_component::io_port_range(unsigned idx)
Device_component::Device_component(Registry<Device_component> & registry,
Env & env,
Driver::Session_component & session,
Driver::Device & device)
: _session(session), _device(device.name()), _reg_elem(registry, *this)
:
_env(env),
_session(session),
_device(device.name()),
_reg_elem(registry, *this)
{
session.cap_quota_guard().withdraw(Cap_quota{1});
_cap_quota += 1;

View File

@ -95,6 +95,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
};
Device_component(Registry<Device_component> & registry,
Env & env,
Session_component & session,
Driver::Device & device);
~Device_component();
@ -113,6 +114,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
private:
Env & _env;
Session_component & _session;
Driver::Device::Name const _device;
size_t _cap_quota { 0 };

View File

@ -66,7 +66,7 @@ Device & Device_model::create_element(Genode::Xml_node node)
{
Device::Name name = node.attribute_value("name", Device::Name());
Device::Type type = node.attribute_value("type", Device::Type());
return *(new (_heap) Device(*this, name, type));
return *(new (_heap) Device(_env, *this, name, type));
}

View File

@ -19,6 +19,7 @@
#include <device_pd.h>
#include <pci.h>
#include <pci_uhci.h>
#include <pci_intel_graphics.h>
using namespace Genode;
using namespace Pci;
@ -172,3 +173,13 @@ bool Driver::pci_device_matches(Session_policy const & policy,
return ret;
}
void Driver::pci_device_specific_info(Device const & dev,
Env & env,
Device_model & model,
Xml_generator & xml)
{
dev.for_pci_config([&] (Device::Pci_config const cfg) {
Driver::pci_intel_graphics_info(cfg, env, model, xml); });
}

View File

@ -28,6 +28,10 @@ namespace Driver {
Genode::Irq_session::Info const info);
bool pci_device_matches(Genode::Session_policy const & policy,
Device const & dev);
void pci_device_specific_info(Device const & dev,
Env & env,
Device_model & model,
Xml_generator & xml);
}
#endif /* _SRC__DRIVERS__PLATFORM__PCI_H_ */

View File

@ -0,0 +1,124 @@
/*
* \brief Platform driver - PCI intel graphics utilities
* \author Stefan Kalkowski
* \date 2022-06-02
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <util/mmio.h>
#include <pci/config.h>
#include <device.h>
namespace Driver {
void pci_intel_graphics_info(Device::Pci_config cfg,
Env & env,
Device_model & model,
Xml_generator & xml);
}
static inline unsigned pci_intel_graphics_generation(Pci::device_t id)
{
struct Device_gen {
Pci::device_t id;
unsigned gen;
};
static Device_gen intel_gpu_generations[] = {
{ 0x7121, 1 }, { 0x7123, 1 }, { 0x7125, 1 }, { 0x1132, 1 },
{ 0x3577, 2 }, { 0x2562, 2 }, { 0x3582, 2 }, { 0x358e, 2 },
{ 0x2572, 2 }, { 0x2582, 3 }, { 0x258a, 3 }, { 0x2592, 3 },
{ 0x2772, 3 }, { 0x27a2, 3 }, { 0x27ae, 3 }, { 0x29b2, 3 },
{ 0x29c2, 3 }, { 0x29d2, 3 }, { 0xa001, 3 }, { 0xa011, 3 },
{ 0x2972, 4 }, { 0x2982, 4 }, { 0x2992, 4 }, { 0x29a2, 4 },
{ 0x2a02, 4 }, { 0x2a12, 4 }, { 0x2a42, 4 }, { 0x2e02, 4 },
{ 0x2e12, 4 }, { 0x2e22, 4 }, { 0x2e32, 4 }, { 0x2e42, 4 },
{ 0x2e92, 4 }, { 0x0042, 5 }, { 0x0046, 5 }, { 0x0102, 6 },
{ 0x010a, 6 }, { 0x0112, 6 }, { 0x0122, 6 }, { 0x0106, 6 },
{ 0x0116, 6 }, { 0x0126, 6 }, { 0x0156, 6 }, { 0x0166, 6 },
{ 0x0152, 7 }, { 0x015a, 7 }, { 0x0162, 7 }, { 0x016a, 7 },
{ 0x0a02, 7 }, { 0x0a06, 7 }, { 0x0a0a, 7 }, { 0x0a0b, 7 },
{ 0x0a0e, 7 }, { 0x0402, 7 }, { 0x0406, 7 }, { 0x040a, 7 },
{ 0x040b, 7 }, { 0x040e, 7 }, { 0x0c02, 7 }, { 0x0c06, 7 },
{ 0x0c0a, 7 }, { 0x0c0b, 7 }, { 0x0c0e, 7 }, { 0x0d02, 7 },
{ 0x0d06, 7 }, { 0x0d0a, 7 }, { 0x0d0b, 7 }, { 0x0d0e, 7 },
{ 0x0a12, 7 }, { 0x0a16, 7 }, { 0x0a1a, 7 }, { 0x0a1b, 7 },
{ 0x0a1e, 7 }, { 0x0412, 7 }, { 0x0416, 7 }, { 0x041a, 7 },
{ 0x041b, 7 }, { 0x041e, 7 }, { 0x0c12, 7 }, { 0x0c16, 7 },
{ 0x0c1a, 7 }, { 0x0c1b, 7 }, { 0x0c1e, 7 }, { 0x0d12, 7 },
{ 0x0d16, 7 }, { 0x0d1a, 7 }, { 0x0d1b, 7 }, { 0x0d1e, 7 },
{ 0x0a22, 7 }, { 0x0a26, 7 }, { 0x0a2a, 7 }, { 0x0a2b, 7 },
{ 0x0a2e, 7 }, { 0x0422, 7 }, { 0x0426, 7 }, { 0x042a, 7 },
{ 0x042b, 7 }, { 0x042e, 7 }, { 0x0c22, 7 }, { 0x0c26, 7 },
{ 0x0c2a, 7 }, { 0x0c2b, 7 }, { 0x0c2e, 7 }, { 0x0d22, 7 },
{ 0x0d26, 7 }, { 0x0d2a, 7 }, { 0x0d2b, 7 }, { 0x0d2e, 7 },
{ 0x0f30, 7 }, { 0x0f31, 7 }, { 0x0f32, 7 }, { 0x0f33, 7 },
};
for (unsigned i = 0;
i < (sizeof(intel_gpu_generations)/(sizeof(Device_gen)));
i++) {
if (id == intel_gpu_generations[i].id)
return intel_gpu_generations[i].gen;
};
/*
* If we do not find something in the array, we assume its
* generation 8 or higher
*/
return 8;
};
void Driver::pci_intel_graphics_info(Device::Pci_config cfg,
Env & env,
Device_model & model,
Xml_generator & xml)
{
enum {
GPU_CLASS_MASK = 0xff0000,
GPU_CLASS_ID = 0x030000,
VENDOR_INTEL = 0x8086
};
if (((cfg.class_code & GPU_CLASS_MASK) != GPU_CLASS_ID) ||
(cfg.vendor_id != VENDOR_INTEL))
return;
/* PCI configuration registers of host bridge */
struct Host_bridge : Mmio
{
struct Gen_old_gmch_control : Register<0x52, 16> {};
struct Gen_6_7_gmch_control : Register<0x50, 16> {};
struct Gen_gmch_control : Register<0x52, 16> {};
using Mmio::Mmio;
};
/* find host bridge */
model.for_each([&] (Device const & dev) {
dev.for_pci_config([&] (Device::Pci_config const cfg) {
if (cfg.bus_num || cfg.dev_num || cfg.func_num)
return;
Attached_io_mem_dataspace io_mem(env, cfg.addr, 0x1000);
Host_bridge config((addr_t)io_mem.local_addr<void>());
unsigned gen = pci_intel_graphics_generation(cfg.device_id);
uint16_t gmch = 0;
if (gen < 6)
gmch = config.read<Host_bridge::Gen_old_gmch_control>();
else if (gen < 8)
gmch = config.read<Host_bridge::Gen_6_7_gmch_control>();
else
gmch = config.read<Host_bridge::Gen_gmch_control>();
xml.attribute("intel_gmch_control", String<16>(Hex(gmch)));
});
});
}

View File

@ -24,7 +24,7 @@ Genode::Capability<Platform::Device_interface>
Session_component::_acquire(Device & device)
{
Device_component * dc = new (heap())
Device_component(_device_registry, *this, device);
Device_component(_device_registry, _env, *this, device);
device.acquire(*this);
return _env.ep().rpc_ep().manage(dc);
};
@ -112,9 +112,6 @@ void Session_component::produce_xml(Xml_generator &xml)
}
Genode::Env & Session_component::env() { return _env; }
Genode::Heap & Session_component::heap() { return _md_alloc; }

View File

@ -56,7 +56,6 @@ class Driver::Session_component
~Session_component();
Env & env();
Heap & heap();
Device_pd & device_pd();