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();