mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-13 22:23:45 +00:00
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
This commit is contained in:
parent
aa9ff3894c
commit
14cfc765c6
@ -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<Igd::Mmio::HWS_PGA_RCSUNIT>(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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<Platform::Device> _device { _platform };
|
||||
Reconstructible<Platform::Device::Irq> _irq { *_device };
|
||||
Reconstructible<Igd::Mmio> _mmio { *_device, _env };
|
||||
Reconstructible<Platform::Device::Mmio<0> > _gmadr { *_device, Platform::Device::Mmio<0>::Index(1) };
|
||||
Reconstructible<Attached_dataspace> _gmadr_mem { _env.rm(), _gmadr->cap() };
|
||||
Constructible<Platform::Device::Mmio<0> > _gmadr { };
|
||||
Constructible<Attached_dataspace> _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<Session_component, Genode::Single_c
|
||||
{
|
||||
if (_session.constructed())
|
||||
_session.destruct();
|
||||
|
||||
_resources.release_aperture_access();
|
||||
}
|
||||
|
||||
bool handle_irq()
|
||||
|
Loading…
x
Reference in New Issue
Block a user