From 8255053242d47585efb6e55f0e28b55c2b3bd4d0 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 27 Jul 2022 17:30:17 +0200 Subject: [PATCH] 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 --- repos/os/src/drivers/platform/common.h | 2 +- repos/os/src/drivers/platform/device.cc | 9 +- repos/os/src/drivers/platform/device.h | 9 +- .../src/drivers/platform/device_component.cc | 15 ++- .../src/drivers/platform/device_component.h | 2 + .../drivers/platform/device_model_policy.cc | 2 +- repos/os/src/drivers/platform/pci.cc | 11 ++ repos/os/src/drivers/platform/pci.h | 4 + .../src/drivers/platform/pci_intel_graphics.h | 124 ++++++++++++++++++ .../src/drivers/platform/session_component.cc | 5 +- .../src/drivers/platform/session_component.h | 1 - 11 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 repos/os/src/drivers/platform/pci_intel_graphics.h diff --git a/repos/os/src/drivers/platform/common.h b/repos/os/src/drivers/platform/common.h index 559a4de6e9..49adc6a7f4 100644 --- a/repos/os/src/drivers/platform/common.h +++ b/repos/os/src/drivers/platform/common.h @@ -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 _dev_handler { _env.ep(), *this, &Common::_handle_devices }; Driver::Root _root; diff --git a/repos/os/src/drivers/platform/device.cc b/repos/os/src/drivers/platform/device.cc index af30b9f288..f26a9fe93c 100644 --- a/repos/os/src/drivers/platform/device.cc +++ b/repos/os/src/drivers/platform/device.cc @@ -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() diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h index 63411c5dec..8c631c6ca1 100644 --- a/repos/os/src/drivers/platform/device.h +++ b/repos/os/src/drivers/platform/device.h @@ -197,7 +197,7 @@ class Driver::Device : private List_model::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::Element friend class List_model; friend class List; + 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 _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); } diff --git a/repos/os/src/drivers/platform/device_component.cc b/repos/os/src/drivers/platform/device_component.cc index c36bd4ace8..5733249c45 100644 --- a/repos/os/src/drivers/platform/device_component.cc +++ b/repos/os/src/drivers/platform/device_component.cc @@ -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 & 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; diff --git a/repos/os/src/drivers/platform/device_component.h b/repos/os/src/drivers/platform/device_component.h index e568fd3ece..ce1a5e4f97 100644 --- a/repos/os/src/drivers/platform/device_component.h +++ b/repos/os/src/drivers/platform/device_component.h @@ -95,6 +95,7 @@ class Driver::Device_component : public Rpc_object & registry, + Env & env, Session_component & session, Driver::Device & device); ~Device_component(); @@ -113,6 +114,7 @@ class Driver::Device_component : public Rpc_object #include #include +#include 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); }); +} diff --git a/repos/os/src/drivers/platform/pci.h b/repos/os/src/drivers/platform/pci.h index c5b9290ad5..ce36bb2927 100644 --- a/repos/os/src/drivers/platform/pci.h +++ b/repos/os/src/drivers/platform/pci.h @@ -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_ */ diff --git a/repos/os/src/drivers/platform/pci_intel_graphics.h b/repos/os/src/drivers/platform/pci_intel_graphics.h new file mode 100644 index 0000000000..630f5ecd43 --- /dev/null +++ b/repos/os/src/drivers/platform/pci_intel_graphics.h @@ -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 +#include +#include + +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()); + unsigned gen = pci_intel_graphics_generation(cfg.device_id); + uint16_t gmch = 0; + + if (gen < 6) + gmch = config.read(); + else if (gen < 8) + gmch = config.read(); + else + gmch = config.read(); + + xml.attribute("intel_gmch_control", String<16>(Hex(gmch))); + }); + }); +} diff --git a/repos/os/src/drivers/platform/session_component.cc b/repos/os/src/drivers/platform/session_component.cc index cefc1ad5da..6f15cb535b 100644 --- a/repos/os/src/drivers/platform/session_component.cc +++ b/repos/os/src/drivers/platform/session_component.cc @@ -24,7 +24,7 @@ Genode::Capability 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; } diff --git a/repos/os/src/drivers/platform/session_component.h b/repos/os/src/drivers/platform/session_component.h index f4a0d63124..dbc91b660a 100644 --- a/repos/os/src/drivers/platform/session_component.h +++ b/repos/os/src/drivers/platform/session_component.h @@ -56,7 +56,6 @@ class Driver::Session_component ~Session_component(); - Env & env(); Heap & heap(); Device_pd & device_pd();