From 14cfc765c64a5bf6daf048b3b30aa275eb9bcccd Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 28 Mar 2025 10:54:55 +0100 Subject: [PATCH] intel/gpu: allocate aperture on demand in order to support running intel/gpu next to boot_fb, which has access to part of the mmio aperture. The aperture is tried to be accessed not before a Platform client (intel/display) or the first GPU client appears. Fixes #5497 --- repos/os/src/driver/gpu/intel/main.cc | 44 +++-- .../src/driver/gpu/intel/platform_session.h | 157 ++++++++++++------ 2 files changed, 137 insertions(+), 64 deletions(-) diff --git a/repos/os/src/driver/gpu/intel/main.cc b/repos/os/src/driver/gpu/intel/main.cc index 5ec6234f8b..74f7b0ccd2 100644 --- a/repos/os/src/driver/gpu/intel/main.cc +++ b/repos/os/src/driver/gpu/intel/main.cc @@ -1187,7 +1187,9 @@ struct Igd::Device _active_vgpu->rcs.with_context_ring([&](auto &context, auto &ring) { context.dump(); - _hw_status_page->dump(); + + with_hw_status_page([&](auto & hw_status) { + hw_status.dump(); }); ring.update_head(context.head_offset()); ring.dump(4096, context.tail_offset() * 2, @@ -1286,12 +1288,12 @@ struct Igd::Device { using namespace Genode; - _resources.with_mmio_gmadr([&](auto &mmio, auto &gmadr) { + _resources.with_mmio([&](auto &mmio) { _resources.with_platform([&](auto &plat_con) { auto const ggtt_base = mmio.base() + (mmio.size() / 2); _ggtt.construct(plat_con, mmio, ggtt_base, - _ggtt_size(gmch_ctl), gmadr.size(), + _ggtt_size(gmch_ctl), _resources.aperture_size(), _resources.aperture_reserved()); if (!_supported(mmio, supported, device_id, revision)) @@ -1299,7 +1301,7 @@ struct Igd::Device _ggtt->dump(); - _vgpu_avail = (gmadr.size() - _resources.aperture_reserved()) + _vgpu_avail = (_resources.aperture_size() - _resources.aperture_reserved()) / Vgpu::DUMMY_MESA_APERTURE_SIZE; reinit(mmio); @@ -1320,12 +1322,6 @@ struct Igd::Device /* setup global hardware status page */ if (!_hw_status_ctx.constructed()) _hw_status_ctx.construct(_md_alloc, *this, 1, 0); - if (!_hw_status_page.constructed()) { - /* global hw_status_ctx becomes never invalid up to now, so using vrange is ok */ - _hw_status_ctx->with_vrange([&](Byte_range_ptr const &vrange) { - _hw_status_page.construct(vrange); - }); - } Mmio::HWS_PGA_RCSUNIT::access_t const addr = _hw_status_ctx->gmaddr(); mmio.write_post(addr); @@ -1567,18 +1563,42 @@ struct Igd::Device return hw_status_page_gmaddr() + Hardware_status_page::Semaphore::OFFSET; } + void with_hw_status_page(auto const &fn) + { + if (!_hw_status_ctx.constructed()) + return; + + if (!_hw_status_page.constructed()) { + /* global hw_status_ctx becomes never invalid up to now, so using vrange is ok */ + _hw_status_ctx->with_vrange([&](Byte_range_ptr const &vrange) { + _hw_status_page.construct(vrange); + }); + } + + if (!_hw_status_page.constructed()) + return; + + fn(*_hw_status_page); + } + /* * Pause the physical ring by setting semaphore value programmed by * 'setup_ring_vram' to 1, causing GPU to spin. */ void hw_status_page_pause_ring(bool pause) { - _hw_status_page->semaphore(pause ? 1 : 0); + with_hw_status_page([&](auto & hw_status) { + hw_status.semaphore(pause ? 1 : 0); }); } uint64_t seqno() { - return _hw_status_page->sequence_number(); + uint64_t seq = 0; + + with_hw_status_page([&](auto & hw_status) { + seq = hw_status.sequence_number(); }); + + return seq; } diff --git a/repos/os/src/driver/gpu/intel/platform_session.h b/repos/os/src/driver/gpu/intel/platform_session.h index f4bbf6245c..83ab9aea2c 100644 --- a/repos/os/src/driver/gpu/intel/platform_session.h +++ b/repos/os/src/driver/gpu/intel/platform_session.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2021-2024 Genode Labs GmbH + * Copyright (C) 2021-2025 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. @@ -400,9 +400,10 @@ class Platform::Resources : Noncopyable, public Hw_ready_state Reconstructible _device { _platform }; Reconstructible _irq { *_device }; Reconstructible _mmio { *_device, _env }; - Reconstructible > _gmadr { *_device, Platform::Device::Mmio<0>::Index(1) }; - Reconstructible _gmadr_mem { _env.rm(), _gmadr->cap() }; + Constructible > _gmadr { }; + Constructible _gmadr_mem { }; + uint64_t const _aperture_size; uint64_t const _aperture_reserved; Region_map_client _rm_gttmm; @@ -412,7 +413,7 @@ class Platform::Resources : Noncopyable, public Hw_ready_state void _reinit() { - with_mmio_gmadr([&](auto &mmio, auto &gmadr) { + with_mmio([&](auto &mmio) { using namespace Igd; @@ -451,42 +452,84 @@ class Platform::Resources : Noncopyable, public Hw_ready_state .writeable = true }).failed()) error("failed to re-attach mmio at gtt offset to gttmm"); - _rm_gmadr.detach(0ul); - if (_rm_gmadr.attach(gmadr.cap(), { - .size = size_t(aperture_reserved()), - .offset = { }, - .use_at = true, - .at = 0, - .executable = { }, - .writeable = true - }).failed()) error("failed to re-attach gmadr"); - }, []() { error("reinit failed"); }); } - Number_of_bytes _sanitized_aperture_size() const + /* + * Always try to reserve 32 MiB for the multiplexer itself but + * we also make sure that 32 MiB are available for the display + * driver (or at least all of the available aperture). We + * prioritize a working display over having the GPU service + * available because investigating the later is futil without + * the former. + */ + static auto constexpr GPU_SERVICE_APERTURE = (32ull << 20); + static auto constexpr DISPLAY_MIN_APERTURE = (32ull << 20); + + Number_of_bytes _sanitized_aperture_size() { - /* - * Always try to reserve 32 MiB for the multiplexer itself but - * we also make sure that 32 MiB are available for the display - * driver (or at least all of the available aperture). We - * prioritize a working display over having the GPU service - * available because investigating the later is futil without - * the former. - */ - auto constexpr GPU_SERVICE_APERTURE = (32ull << 20); - auto constexpr DISPLAY_MIN_APERTURE = (32ull << 20); - - if (_gmadr->size() <= DISPLAY_MIN_APERTURE) - return _gmadr->size(); + auto apert_reserved = _aperture_size; + if (_aperture_size <= DISPLAY_MIN_APERTURE) + apert_reserved = _aperture_size; + else /* guard against non 2^x aperture size */ - if ((_gmadr->size() - GPU_SERVICE_APERTURE) < DISPLAY_MIN_APERTURE) - return DISPLAY_MIN_APERTURE; + if ((_aperture_size - GPU_SERVICE_APERTURE) < DISPLAY_MIN_APERTURE) + apert_reserved = DISPLAY_MIN_APERTURE; + else + apert_reserved = _aperture_size - GPU_SERVICE_APERTURE; - return _gmadr->size() - GPU_SERVICE_APERTURE; + log("Aperture max: ", Number_of_bytes(_aperture_size), + " display: ", Number_of_bytes(apert_reserved)); + + /* reserved space is used to calculate vGPU available */ + if (_aperture_size == apert_reserved) + warning("GPU service not usable due to insufficient aperture space"); + + return apert_reserved; + } + + Number_of_bytes _aperture_size_via_device_rom() + { + auto apert_size = DISPLAY_MIN_APERTURE; + + _platform.with_xml([&](auto const &node) { + node.for_each_sub_node("device", [&] (Xml_node const &dev) { + dev.for_each_sub_node("pci-config", [&] (Xml_node const &cfg) { + + if (cfg.attribute_value("vendor_id", 0) != 0x8086) + return; + + dev.for_each_sub_node("io_mem", [&] (Xml_node const &mem) { + if (mem.attribute_value("pci_bar", ~0u) != 2) + return; + + apert_size = mem.attribute_value("size", apert_size); + }); + }); + }); + }); + + return apert_size; + } + + bool _make_aperture_accessible() + { + bool reconstructed = false; + + if (_device.constructed() && !_gmadr.constructed()) { + _gmadr.construct(*_device, Platform::Device::Mmio<0>::Index(1)); + reconstructed = true; + } + + if (_gmadr.constructed() && !_gmadr_mem.constructed()) { + _gmadr_mem.construct(_env.rm(), _gmadr->cap()); + reconstructed = true; + } + + return reconstructed; } public: @@ -495,19 +538,13 @@ class Platform::Resources : Noncopyable, public Hw_ready_state : _env(env), _irq_cap(irq), + _aperture_size(_aperture_size_via_device_rom()), _aperture_reserved(_sanitized_aperture_size()), _rm_gttmm(rm.create(_mmio->size())), _rm_gmadr(rm.create(aperture_reserved())), _range_gttmm(1ul << 30, _mmio->size()), _range_gmadr(1ul << 29, aperture_reserved()) { - log("Aperture max: ", Number_of_bytes(_gmadr->size()), - " display: ", Number_of_bytes(_aperture_reserved)); - - /* reserved space is used to calculate vGPU available */ - if (_gmadr->size() == _aperture_reserved) - warning("GPU service not usable due to insufficient aperture space"); - _irq->sigh(_irq_cap); /* GTT starts at half of the mmio memory */ @@ -554,18 +591,10 @@ class Platform::Resources : Noncopyable, public Hw_ready_state } } - void with_mmio_gmadr(auto const &fn, auto const &fn_error) - { - if (!_mmio.constructed() || !_gmadr.constructed()) { - fn_error(); - return; - } - - fn(*_mmio, *_gmadr); - } - void with_gmadr(auto const offset, auto const &fn, auto const &fn_error) { + _make_aperture_accessible(); + if (!_gmadr.constructed() || !_gmadr_mem.constructed()) { fn_error(); return; @@ -592,6 +621,23 @@ class Platform::Resources : Noncopyable, public Hw_ready_state void with_gttm_gmadr(auto const &fn) { + bool attach_required = _make_aperture_accessible(); + + if (attach_required) { + _rm_gmadr.detach(0ul); + if (_rm_gmadr.attach(_gmadr->cap(), { + .size = size_t(aperture_reserved()), + .offset = { }, + .use_at = true, + .at = 0, + .executable = { }, + .writeable = true + }).failed()) { + error("failed to re-attach gmadr"); + return; + } + } + fn(_platform, _rm_gttmm, _range_gttmm, _rm_gmadr, _range_gmadr); } @@ -605,25 +651,30 @@ class Platform::Resources : Noncopyable, public Hw_ready_state _irq->sigh(_irq_cap); _mmio.construct(*_device, _env); - _gmadr.construct(*_device, Platform::Device::Mmio<0>::Index(1)); - _gmadr_mem.construct(_env.rm(), _gmadr->cap()); _reinit(); } void release_device() { - _gmadr_mem.destruct(); - _gmadr.destruct(); + release_aperture_access(); + _mmio.destruct(); _irq.destruct(); _device.destruct(); } + void release_aperture_access() + { + _gmadr_mem.destruct(); + _gmadr.destruct(); + } + /* * Reserved aperture for platform service */ uint64_t aperture_reserved() const { return _aperture_reserved; } + uint64_t aperture_size() const { return _aperture_size; } uint64_t gtt_reserved() const { @@ -695,6 +746,8 @@ class Platform::Root : public Root_component