gpu/intel: make aperture configurable

Fixes #5124
This commit is contained in:
Alexander Boettcher 2024-02-20 14:22:28 +01:00 committed by Christian Helmuth
parent 77f5ef3bcd
commit 12df9bf450
4 changed files with 76 additions and 20 deletions

View File

@ -598,7 +598,7 @@ struct Igd::Device
struct Vgpu : Genode::Fifo<Vgpu>::Element
{
enum {
APERTURE_SIZE = 4096ul,
DUMMY_MESA_APERTURE_SIZE = 4096ul,
MAX_FENCES = 16,
INFO_SIZE = 4096,
@ -635,7 +635,7 @@ struct Igd::Device
_device.vgpu_created();
_info = Gpu::Info_intel(_device.id(), _device.features(),
APERTURE_SIZE,
DUMMY_MESA_APERTURE_SIZE,
_id, Gpu::Sequence_number { .value = 0 },
_device._revision,
_device._slice_mask,
@ -1281,14 +1281,15 @@ struct Igd::Device
_ggtt.construct(plat_con, mmio, ggtt_base,
_ggtt_size(gmch_ctl), gmadr.size(),
APERTURE_RESERVED);
_resources.aperture_reserved());
if (!_supported(mmio, supported, device_id, revision))
throw Unsupported_device();
_ggtt->dump();
_vgpu_avail = (gmadr.size() - APERTURE_RESERVED) / Vgpu::APERTURE_SIZE;
_vgpu_avail = (gmadr.size() - _resources.aperture_reserved())
/ Vgpu::DUMMY_MESA_APERTURE_SIZE;
reinit(mmio);
});
@ -2503,7 +2504,8 @@ struct Main : Irq_ack_handler, Gpu_reset_handler
&Main::handle_irq };
Signal_handler<Main> _config_sigh { _env.ep(), *this,
&Main::_handle_config_update };
Platform::Resources _dev { _env, _rm, _irq_dispatcher };
Platform::Resources _dev { _env, _rm, _irq_dispatcher,
_config_aperture_size() };
Signal_handler<Main> _system_sigh { _env.ep(), *this,
&Main::_system_update };
@ -2559,6 +2561,16 @@ struct Main : Irq_ack_handler, Gpu_reset_handler
});
}
Number_of_bytes _config_aperture_size() const
{
auto aperture_size = Number_of_bytes(64ull << 20);
if (_config_rom.valid())
aperture_size = _config_rom.xml().attribute_value("max_framebuffer_memory", aperture_size);
return aperture_size;
}
void _handle_config_update()
{
_config_rom.update();
@ -2661,7 +2673,7 @@ struct Main : Irq_ack_handler, Gpu_reset_handler
_dev.with_mmio([&](auto &mmio) {
_dev.with_platform([&](auto &plat_con) {
auto const base = mmio.base() + (mmio.size() / 2);
Igd::Ggtt(plat_con, mmio, base, Igd::GTT_RESERVED, 0, 0);
Igd::Ggtt(plat_con, mmio, base, _dev.gtt_reserved(), 0, 0);
});
}, []() {
error("reset failed");

View File

@ -286,6 +286,7 @@ class Platform::Resources : Noncopyable
Env & _env;
Signal_context_capability const _irq_cap;
Platform::Connection _platform { _env };
Reconstructible<Platform::Device> _device { _platform };
Reconstructible<Platform::Device::Irq> _irq { *_device };
@ -293,6 +294,8 @@ class Platform::Resources : Noncopyable
Reconstructible<Platform::Device::Mmio<0> > _gmadr { *_device, Platform::Device::Mmio<0>::Index(1) };
Reconstructible<Attached_dataspace> _gmadr_mem { _env.rm(), _gmadr->cap() };
uint64_t const _aperture_reserved;
Region_map_client _rm_gttmm;
Region_map_client _rm_gmadr;
Range _range_gttmm;
@ -312,7 +315,7 @@ class Platform::Resources : Noncopyable
size_t const gttm_half_size = mmio.size() / 2;
off_t const gtt_offset = gttm_half_size;
if (gttm_half_size < GTT_RESERVED) {
if (gttm_half_size < gtt_reserved()) {
Genode::error("GTTM size too small");
return;
}
@ -324,25 +327,59 @@ class Platform::Resources : Noncopyable
/* attach beginning of GTT */
_rm_gttmm.detach(gtt_offset);
_rm_gttmm.attach_at(mmio.cap(), gtt_offset,
GTT_RESERVED, gtt_offset);
gtt_reserved(), gtt_offset);
_rm_gmadr.detach(0ul);
_rm_gmadr.attach_at(gmadr.cap(), 0ul, APERTURE_RESERVED);
_rm_gmadr.attach_at(gmadr.cap(), 0ul, aperture_reserved());
}, []() {
error("reinit failed");
});
}
Number_of_bytes _sanitized_aperture_size(Number_of_bytes memory) const
{
/*
* Ranges of global GTT (ggtt) are handed in page granularity (4k)
* to the platform client (intel display driver).
* 512 page table entries a 4k fit into one page, which adds up to
* 2M virtual address space.
*/
auto constexpr shift_2mb = 21ull;
auto constexpr MIN_MEMORY_FOR_MULTIPLEXER = 4ull << shift_2mb;
/* align requests to 2M and enforce 2M as minimum */
memory = memory & _align_mask(shift_2mb);
if (memory < (1ull << shift_2mb))
memory = 1ull << shift_2mb;
if (_gmadr->size() >= MIN_MEMORY_FOR_MULTIPLEXER) {
if (memory > _gmadr->size() - MIN_MEMORY_FOR_MULTIPLEXER)
memory = _gmadr->size() - MIN_MEMORY_FOR_MULTIPLEXER;
} else {
/* paranoia case, should never trigger */
memory = _gmadr->size() / 2;
error("aperture smaller than ", MIN_MEMORY_FOR_MULTIPLEXER,
" will not work properly");
}
log("Maximum aperture size ", Number_of_bytes(_gmadr->size()));
log(" - available framebuffer memory for display driver: ", memory);
return memory;
}
public:
Resources(Env &env, Rm_connection &rm, Signal_context_capability irq)
Resources(Env &env, Rm_connection &rm, Signal_context_capability irq,
Number_of_bytes const &aperture)
:
_env(env),
_irq_cap(irq),
_aperture_reserved(_sanitized_aperture_size(aperture)),
_rm_gttmm(rm.create(_mmio->size())),
_rm_gmadr(rm.create(Igd::APERTURE_RESERVED)),
_rm_gmadr(rm.create(aperture_reserved())),
_range_gttmm(1ul << 30, _mmio->size()),
_range_gmadr(1ul << 29, _gmadr->size())
_range_gmadr(1ul << 29, aperture_reserved())
{
_irq->sigh(_irq_cap);
@ -350,7 +387,7 @@ class Platform::Resources : Noncopyable
size_t const gttm_half_size = _mmio->size() / 2;
off_t const gtt_offset = gttm_half_size;
if (gttm_half_size < Igd::GTT_RESERVED) {
if (gttm_half_size < gtt_reserved()) {
Genode::error("GTTM size too small");
return;
}
@ -359,9 +396,9 @@ class Platform::Resources : Noncopyable
/* attach the rest of the GTT as dummy RAM */
auto const dummmy_gtt_ds = _env.ram().alloc(Igd::PAGE_SIZE);
auto remainder = gttm_half_size - Igd::GTT_RESERVED;
auto remainder = gttm_half_size - gtt_reserved();
for (off_t offset = gtt_offset + Igd::GTT_RESERVED;
for (off_t offset = gtt_offset + gtt_reserved();
remainder > 0;
offset += Igd::PAGE_SIZE, remainder -= Igd::PAGE_SIZE) {
@ -435,6 +472,17 @@ class Platform::Resources : Noncopyable
_irq.destruct();
_device.destruct();
}
/*
* Reserved aperture for platform service
*/
uint64_t aperture_reserved() const { return _aperture_reserved; }
uint64_t gtt_reserved() const
{
/* reserved GTT for platform service, GTT entry is 8 byte */
return (aperture_reserved() / Igd::PAGE_SIZE) * 8;
}
};

View File

@ -30,10 +30,6 @@ namespace Igd {
enum {
PAGE_SIZE = 4096,
/* reserved aperture for platform service */
APERTURE_RESERVED = 64u<<20,
/* reserved GTT for platform service, GTT entry is 8 byte */
GTT_RESERVED = (APERTURE_RESERVED/PAGE_SIZE) * 8,
};
inline void wmb() { asm volatile ("sfence": : :"memory"); }

View File

@ -229,7 +229,7 @@ append_if $use_gpu config {
<service name="Gpu"/>
<service name="Platform"/>
</provides>
<config>
<config max_framebuffer_memory="64M">
<device vendor="0x8086" device="0x1606" generation="8" platform="broadwell" description="HD Graphics (BDW GT1 ULT)"/>
<device vendor="0x8086" device="0x1616" generation="8" platform="broadwell" description="HD Graphics 5500 (BDW GT2 ULT)"/>
<device vendor="0x8086" device="0x1622" generation="8" platform="broadwell" description="Iris Pro Graphics 6200 (BDW GT3e)"/>