From 2aa01e309ced36ea439ea93934959c13efcacd03 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Fri, 1 Jul 2022 14:35:04 +0200 Subject: [PATCH] gpu/intel: GEN12+ * clock frequency * topology * exec lists * IRQ handling * improved resource management issue #4664 --- repos/os/include/gpu/info_intel.h | 56 +++- repos/os/src/drivers/gpu/intel/main.cc | 264 +++++++++++---- repos/os/src/drivers/gpu/intel/mmio.h | 300 ++++++++++++++++-- .../src/drivers/gpu/intel/ppgtt_allocator.h | 6 +- 4 files changed, 527 insertions(+), 99 deletions(-) diff --git a/repos/os/include/gpu/info_intel.h b/repos/os/include/gpu/info_intel.h index c7295ad7d0..bb30af4b21 100644 --- a/repos/os/include/gpu/info_intel.h +++ b/repos/os/include/gpu/info_intel.h @@ -33,6 +33,7 @@ struct Gpu::Info_intel using Features = Genode::uint32_t; using size_t = Genode::size_t; using Context_id = Genode::uint32_t; + using uint8_t = Genode::uint8_t; Chip_id chip_id; Features features; @@ -41,16 +42,55 @@ struct Gpu::Info_intel Sequence_number last_completed; - struct Revision { Genode::uint8_t value; } revision; - struct Slice_mask { unsigned value; } slice_mask; - struct Subslice_mask { unsigned value; } subslice_mask; - struct Eu_total { unsigned value; } eus; - struct Subslices { unsigned value; } subslices; + struct Revision { Genode::uint8_t value; } revision; + struct Slice_mask { unsigned value; } slice_mask; + struct Subslice_mask { unsigned value; } subslice_mask; + struct Eu_total { unsigned value; } eus; + struct Subslices { unsigned value; } subslices; + struct Clock_frequency { unsigned value; } clock_frequency; + + struct Topology + { + enum { + MAX_SLICES = 3, + MAX_SUBSLICES = 32, + MAX_EUS = 16, + }; + + uint8_t slice_mask { 0 }; + uint8_t subslice_mask[MAX_SLICES * (MAX_SUBSLICES / 8)] { }; + uint8_t eu_mask[MAX_SLICES * MAX_SUBSLICES * (MAX_EUS / 8)] { }; + + uint8_t max_slices { 0 }; + uint8_t max_subslices { 0 }; + uint8_t max_eus_per_subslice { 0 }; + + uint8_t ss_stride { 0 }; + uint8_t eu_stride { 0 }; + + bool valid { false }; + + bool has_subslice(unsigned slice, unsigned subslice) + { + unsigned ss_idx = subslice / 8; + uint8_t mask = subslice_mask[slice * ss_stride + ss_idx]; + return mask & (1u << (subslice % 8)); + } + + unsigned eu_idx(unsigned slice, unsigned subslice) + { + unsigned slice_stride = max_slices * eu_stride; + return slice * slice_stride + subslice * eu_stride; + } + }; + + struct Topology topology { }; Info_intel(Chip_id chip_id, Features features, size_t aperture_size, Context_id ctx_id, Sequence_number last, Revision rev, Slice_mask s_mask, Subslice_mask ss_mask, - Eu_total eu, Subslices subslice) + Eu_total eu, Subslices subslice, Clock_frequency clock_frequency, + Topology topology) : chip_id(chip_id), features(features), aperture_size(aperture_size), ctx_id(ctx_id), @@ -59,7 +99,9 @@ struct Gpu::Info_intel slice_mask(s_mask), subslice_mask(ss_mask), eus(eu), - subslices(subslice) + subslices(subslice), + clock_frequency(clock_frequency), + topology(topology) { } }; diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index f0f1189553..9a4397d1e9 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -56,7 +56,7 @@ namespace Igd { struct Igd::Device_info { - enum Platform { UNKNOWN, BROADWELL, SKYLAKE, KABYLAKE, WHISKEYLAKE }; + enum Platform { UNKNOWN, BROADWELL, SKYLAKE, KABYLAKE, WHISKEYLAKE, TIGERLAKE }; enum Stepping { A0, B0, C0, D0, D1, E0, F0, G0 }; uint16_t id; @@ -89,23 +89,52 @@ struct Igd::Device ** PCI ** *********/ - struct Pci_backend_alloc : Utils::Backend_alloc + struct Pci_backend_alloc : Utils::Backend_alloc, Ram_allocator { + Env &_env; Platform::Connection &_pci; - Pci_backend_alloc(Platform::Connection &pci) : _pci(pci) { } + Pci_backend_alloc(Env &env, Platform::Connection &pci) + : _env(env), _pci(pci) { } Ram_dataspace_capability alloc(size_t size) override { - return _pci.retry_with_upgrade(Genode::Ram_quota{PAGE_SIZE}, - Genode::Cap_quota{8}, [&] () { - return _pci.alloc_dma_buffer(size, Genode::UNCACHED); }); + enum { + UPGRADE_RAM = 8 * PAGE_SIZE, + UPGRADE_CAPS = 2, + UPGRADE_ATTEMPTS = ~0U + }; + + return retry( + [&] () { + return retry( + [&] () { return _pci.Client::alloc_dma_buffer(size, UNCACHED); }, + [&] () + { + if (_env.pd().avail_caps().value < UPGRADE_CAPS) { + warning("alloc dma buffer: out if caps"); + throw Gpu::Session::Out_of_caps(); + } + + _pci.upgrade_caps(UPGRADE_CAPS); + }, + UPGRADE_ATTEMPTS); + }, + [&] () + { + if (_env.pd().avail_ram().value < size) { + warning("alloc dma buffer: out of ram"); + throw Gpu::Session::Out_of_ram(); + } + _pci.upgrade_ram(size); + }, + UPGRADE_ATTEMPTS); } void free(Ram_dataspace_capability cap) override { if (!cap.valid()) { - Genode::error("could not free, capability invalid"); + error("could not free, capability invalid"); return; } @@ -117,15 +146,28 @@ struct Igd::Device return _pci.dma_addr(ds_cap); } - } _pci_backend_alloc { _platform }; + /** + * RAM allocator interface + */ + size_t dataspace_size(Ram_dataspace_capability) const override { return 0; } + + Alloc_result try_alloc(size_t size, Cache) override + { + return alloc(size); + } + + } _pci_backend_alloc { _env, _platform }; + + Device_info _info { }; + Gpu::Info_intel::Revision _revision { }; + Gpu::Info_intel::Slice_mask _slice_mask { }; + Gpu::Info_intel::Subslice_mask _subslice_mask { }; + Gpu::Info_intel::Eu_total _eus { }; + Gpu::Info_intel::Subslices _subslices { }; + Gpu::Info_intel::Topology _topology { }; + Gpu::Info_intel::Clock_frequency _clock_frequency { }; - Device_info _info { }; - Gpu::Info_intel::Revision _revision { }; - Gpu::Info_intel::Slice_mask _slice_mask { }; - Gpu::Info_intel::Subslice_mask _subslice_mask { }; - Gpu::Info_intel::Eu_total _eus { }; - Gpu::Info_intel::Subslices _subslices { }; bool _supported(Xml_node & supported, uint16_t dev_id, @@ -147,10 +189,10 @@ struct Igd::Device return; struct Igd::Device_info const info { - .id = device, - .generation = generation, - .platform = platform_type(platform), - .features = 0 + .id = device, + .generation = generation, + .platform = platform_type(platform), + .features = 0, }; if (info.platform == Igd::Device_info::Platform::UNKNOWN) @@ -158,7 +200,8 @@ struct Igd::Device if (info.id == dev_id) { _info = info; - _revision.value = rev_id; + _revision.value = rev_id; + _clock_frequency.value = _mmio.clock_frequency(generation); found = true; return; @@ -178,6 +221,8 @@ struct Igd::Device return Igd::Device_info::Platform::KABYLAKE; if (platform == "whiskeylake") return Igd::Device_info::Platform::WHISKEYLAKE; + if (platform == "tigerlake") + return Igd::Device_info::Platform::TIGERLAKE; return Igd::Device_info::UNKNOWN; } @@ -185,7 +230,6 @@ struct Igd::Device ** GGTT ** **********/ - size_t _ggtt_size() { /* @@ -575,7 +619,9 @@ struct Igd::Device _device._slice_mask, _device._subslice_mask, _device._eus, - _device._subslices); + _device._subslices, + _device._clock_frequency, + _device._topology); } ~Vgpu() @@ -622,7 +668,9 @@ struct Igd::Device + ((_device.generation().value == 9) ? 6 : 0) + ((_device.generation().value == 8) ? 20 : 22) /* epilog + w/a */ + (dc_flush_wa ? 12 : 0); - if (!el.ring_avail(need)) { el.ring_reset_and_fill_zero(); } + + if (!el.ring_avail(need)) + el.ring_reset_and_fill_zero(); /* save old tail */ Ring_buffer::Index const tail = el.ring_tail(); @@ -888,6 +936,23 @@ struct Igd::Device _mmio.write(desc[0]); } + void _submit_execlist_gen12(Engine &engine) + { + if (_mmio.read() == 0) + return; + + Execlist &el = *engine.execlist; + + _mmio.write(el.elem0().low(), 0); + _mmio.write(el.elem0().high(), 1); + + for (unsigned i = 2; i < 16; i++) + _mmio.write(0, i); + + /* load SQ to EQ */ + _mmio.write(1); + } + Vgpu *_unschedule_current_vgpu() { Vgpu *result = nullptr; @@ -916,7 +981,10 @@ struct Igd::Device _mmio.flush_gfx_tlb(); - _submit_execlist(rcs); + if (_info.generation < 11) + _submit_execlist(rcs); + else + _submit_execlist_gen12(rcs); _active_vgpu = gpu; _timer.trigger_once(WATCHDOG_TIMEOUT); @@ -926,11 +994,6 @@ struct Igd::Device ** INTR ** **********/ - void _clear_rcs_iir(Mmio::GT_0_INTERRUPT_IIR::access_t const v) - { - _mmio.write_post(v); - } - /** * \return true, if Vgpu is done and has not further work */ @@ -989,7 +1052,8 @@ struct Igd::Device if (!_active_vgpu) { return; } Genode::error("watchdog triggered: engine stuck," - " vGPU=", _active_vgpu->id()); + " vGPU=", _active_vgpu->id(), " IRQ: ", + Hex(_mmio.read_irq_vector(_info.generation))); _mmio.dump(); _mmio.error_dump(); _mmio.fault_dump(); @@ -1021,7 +1085,7 @@ struct Igd::Device _mmio.reset(_info.generation); _mmio.clear_errors(); _mmio.init(); - _mmio.enable_intr(); + _mmio.enable_intr(_info.generation); } /** @@ -1084,6 +1148,9 @@ struct Igd::Device _subslices.value ++; _init_eu_total(3, SUBSLICE_MAX, 8); + } else + if (_info.generation == 12) { + _init_topology_gen12(); } else Genode::error("unsupported platform ", (int)_info.platform); @@ -1093,6 +1160,46 @@ struct Igd::Device _timer.sigh(_watchdog_timeout_sigh); } + void _init_topology_gen12() + { + /* NOTE: This needs to be different for DG2 and Xe_HP */ + _topology.max_slices = 1; + _topology.max_subslices = 6; + _topology.max_eus_per_subslice = 16; + _topology.ss_stride = 1; /* roundup(6/8) */ + _topology.eu_stride = 2; /* 16/8 */ + + /* NOTE: 1 for >=12.5 */ + _topology.slice_mask = _mmio.read(); + if (_topology.slice_mask > 1) + error("topology: slices > 1"); + + uint32_t dss_en = _mmio.read(); + memcpy(_topology.subslice_mask, &dss_en, sizeof(dss_en)); + + /* Gen12 uses dual-subslices */ + uint8_t eu_en_fuse = ~_mmio.read(); + uint16_t eu_en { 0 }; + for (unsigned i = 0; i < _topology.max_eus_per_subslice / 2; i++) { + if (eu_en_fuse & (1u << i)) { + _eus.value += 2; + eu_en |= (3u << (i * 2)); + } + } + + for (unsigned i = 0; i < _topology.max_subslices; i++) { + if (_topology.has_subslice(0, i)) { + _subslices.value++; + unsigned offset = _topology.eu_idx(0, i); + for (unsigned j = 0; j < _topology.eu_stride; j++) { + _topology.eu_mask[offset + j] = (eu_en >> (8 * j)) & 0xff; + } + } + } + + _topology.valid = true; + } + void _clock_gating() { if (_info.platform == Device_info::Platform::KABYLAKE) { @@ -1382,22 +1489,24 @@ struct Igd::Device _clear_fence(id); } - unsigned handle_irq() + bool handle_irq() { - Mmio::MASTER_INT_CTL::access_t master = _mmio.read(); + bool display_irq = _mmio.display_irq(_info.generation); /* handle render interrupts only */ - if (Mmio::MASTER_INT_CTL::Render_interrupts_pending::get(master) == 0) - return master; + if (_mmio.render_irq(_info.generation) == false) + return display_irq; - _mmio.disable_master_irq(); + _mmio.disable_master_irq(_info.generation); - Mmio::GT_0_INTERRUPT_IIR::access_t const v = _mmio.read(); + Mmio::GEN12_RENDER_INTR_VEC::access_t const v = _mmio.read_irq_vector(_info.generation); - bool const ctx_switch = Mmio::GT_0_INTERRUPT_IIR::Cs_ctx_switch_interrupt::get(v); - bool const user_complete = Mmio::GT_0_INTERRUPT_IIR::Cs_mi_user_interrupt::get(v); + bool const ctx_switch = Mmio::GEN12_RENDER_INTR_VEC::Cs_ctx_switch_interrupt::get(v); + bool const user_complete = Mmio::GEN12_RENDER_INTR_VEC::Cs_mi_user_interrupt::get(v); - if (v) { _clear_rcs_iir(v); } + if (v) { + _mmio.clear_render_irq(_info.generation, v); + } Vgpu *notify_gpu = nullptr; if (user_complete) { @@ -1428,10 +1537,10 @@ struct Igd::Device } } - return master; + return display_irq; } - void enable_master_irq() { _mmio.enable_master_irq(); } + void enable_master_irq() { _mmio.enable_master_irq(_info.generation); } private: @@ -1465,10 +1574,10 @@ class Gpu::Session_component : public Genode::Session_object Genode::Env &_env; Genode::Region_map &_rm; Constrained_ram_allocator _ram; - Heap _heap { _ram, _rm }; + Igd::Device &_device; + Heap _heap { _device._pci_backend_alloc, _rm }; Capability _session_cap { cap() }; - Igd::Device &_device; Igd::Device::Vgpu _vgpu; struct Resource_guard @@ -1483,24 +1592,38 @@ class Gpu::Session_component : public Genode::Session_object { } /* worst case */ - bool avail_caps() { return _cap_quota_guard.have_avail(Cap_quota { 5 }); } + bool avail_caps() { return _cap_quota_guard.have_avail(Cap_quota { 15 }); } - /* size + possible heap allocations */ + /* size + possible heap allocations + possible page table allocation + + * + 16KB for 'ep.manage' + unkown overhead */ bool avail_ram(size_t size = 0) { - return _ram_quota_guard.have_avail(Ram_quota { size + 2*1024*1024 }); } + return _ram_quota_guard.have_avail(Ram_quota { size + 2*1024*1024+4096 + + 1024*1024 + 16*1024 + 1024*1024}); } - void withdraw(size_t caps, size_t ram) + void withdraw(size_t caps_old, size_t caps_new, + size_t ram_old, size_t ram_new) { + size_t caps = caps_old > caps_new ? caps_old - caps_new : 0; + size_t ram = ram_old > ram_new ? ram_old - ram_new : 0; + try { _cap_quota_guard.withdraw(Cap_quota { caps }); _ram_quota_guard.withdraw(Ram_quota { ram }); - } catch (... /* intentional catch-all */) { + } catch (Genode::Out_of_caps) { /* * At this point something in the accounting went wrong * and as quick-fix let the client abort rather than the * multiplexer. */ - throw Service_denied(); + Genode::error("Quota guard out of caps! from ", __builtin_return_address(0)); + throw Gpu::Session::Out_of_caps(); + } catch (Genode::Out_of_ram) { + Genode::error("Quota guard out of ram! from ", __builtin_return_address(0)); + Genode::error("guard ram: ", _ram_quota_guard.avail().value, " requested: ", ram); + throw Gpu::Session::Out_of_ram(); + } catch (...) { + Genode::error("Unknown exception in 'Resourcd_guard::withdraw'"); + throw; } } @@ -1600,9 +1723,13 @@ class Gpu::Session_component : public Genode::Session_object void _apply_buffer_local(Gpu::Buffer_id id, FN const &fn) { Buffer_local::Id_space::Id local_id { .value = id.value }; - _buffer_space.apply(local_id, [&] (Buffer_local &buffer) { - fn(buffer); - }); + try { + _buffer_space.apply(local_id, [&] (Buffer_local &buffer) { + fn(buffer); + }); + } catch (Buffer_local::Id_space::Unknown_id) { + error("Unknown id: ", id.value); + } } Genode::uint64_t seqno { 0 }; @@ -1758,8 +1885,8 @@ class Gpu::Session_component : public Genode::Session_object size_t ram_before = _env.pd().avail_ram().value; Ram_dataspace_capability ds_cap = _device.alloc_buffer(_heap, size); - addr_t phys_addr = _device.dma_addr(ds_cap); - Buffer *buffer = new (&_heap) Buffer(ds_cap, phys_addr, _session_cap); + addr_t phys_addr = _device.dma_addr(ds_cap); + Buffer *buffer = new (&_heap) Buffer(ds_cap, phys_addr, _session_cap); _env.ep().manage(*buffer); try { @@ -1768,17 +1895,17 @@ class Gpu::Session_component : public Genode::Session_object _env.ep().dissolve(*buffer); destroy(&_heap, buffer); _device.free_buffer(_heap, ds_cap); - throw Gpu::Session_component::Conflicting_id(); + return Dataspace_capability(); } size_t caps_after = _env.pd().avail_caps().value; size_t ram_after = _env.pd().avail_ram().value; - /* limit to buffer size */ - buffer->ram_used = min(ram_before - ram_after, size); - buffer->caps_used = (caps_before - caps_after) > 0; + /* limit to buffer size for replenish */ + buffer->ram_used = min(ram_before > ram_after ? ram_before - ram_after : 0, size); + buffer->caps_used = caps_before > caps_after ? true : false; - _resource_guard.withdraw(caps_before - caps_after, buffer->ram_used); + _resource_guard.withdraw(caps_before, caps_after, ram_before, ram_after); return ds_cap; } @@ -1877,8 +2004,8 @@ class Gpu::Session_component : public Genode::Session_object size_t caps_after = _env.pd().avail_caps().value; size_t ram_after = _env.pd().avail_ram().value; - _resource_guard.withdraw(caps_before - caps_after, - ram_before - ram_after); + _resource_guard.withdraw(caps_before, caps_after, + ram_before , ram_after); return true; }; @@ -1956,8 +2083,8 @@ class Gpu::Session_component : public Genode::Session_object size_t caps_after = _env.pd().avail_caps().value; size_t ram_after = _env.pd().avail_ram().value; - _resource_guard.withdraw(caps_before - caps_after, - ram_before - ram_after); + _resource_guard.withdraw(caps_before, caps_after, + ram_before, ram_after); return true; } @@ -2081,7 +2208,7 @@ class Gpu::Root : public Gpu::Root_component using namespace Genode; return new (md_alloc()) - Session_component(_env, _env.ep(), _env.ram(), _env.rm(), + Session_component(_env, _env.ep(), _device->_pci_backend_alloc, _env.rm(), resources, session_label_from_args(args), session_diag_from_args(args), @@ -2198,9 +2325,9 @@ struct Main : Irq_ack_handler, Gpu_reset_handler void handle_irq() { - unsigned master = 0; + bool display_irq = false; if (_igd_device.constructed()) - master = _igd_device->handle_irq(); + display_irq = _igd_device->handle_irq(); /* GPU not present forward all IRQs to platform client */ else { _platform_root.handle_irq(); @@ -2211,10 +2338,9 @@ struct Main : Irq_ack_handler, Gpu_reset_handler * GPU present check for display engine related IRQs before calling platform * client */ - using Master = Igd::Mmio::MASTER_INT_CTL; - if (Master::De_interrupts_pending::get(master) && - (_platform_root.handle_irq())) + if (display_irq && _platform_root.handle_irq()) { return; + } ack_irq(); } diff --git a/repos/os/src/drivers/gpu/intel/mmio.h b/repos/os/src/drivers/gpu/intel/mmio.h index fa99778151..c5a4358486 100644 --- a/repos/os/src/drivers/gpu/intel/mmio.h +++ b/repos/os/src/drivers/gpu/intel/mmio.h @@ -194,6 +194,66 @@ class Igd::Mmio : public Platform::Device::Mmio struct GT_3_INTERRUPT_IIR : GT_3_INTERRUPT<0x44338> { }; struct GT_3_INTERRUPT_IER : GT_3_INTERRUPT<0x4433C> { }; + /** + * GEN11+ interrupt registers + * IHD-OS-TGL-Vol 2c-12.21 part1 p. 1039 ff. + */ + struct GEN12_GFX_MSTR_INTR : Register<0x190010, 32> + { + struct Master_interrupt_enable : Bitfield<31, 1> { }; + struct Display : Bitfield<16, 1> { }; + struct Gt_dw_1 : Bitfield< 1, 1> { }; + struct Gt_dw_0 : Bitfield< 0, 1> { }; + }; + + /* p. 1089 */ + struct GEN12_GT_INTR_DW0 : Register<0x190018, 32> + { + struct Rcs0 : Bitfield<0, 1> { }; + }; + + /* p. 1091 */ + struct GEN12_INTR_IDENTITY_REG0 : Register<0x190060, 32> + { + struct Valid : Bitfield<31, 1> { }; + struct Engine_interrupt : Bitfield<0, 16> { }; + }; + + /* + * p. 1092 + * + * Select engine ID to read INTR_IDENTITY from, use only one bit at a time, + * layout is as INTR_DW0 register + */ + struct GEN12_INTR_IIR_SELECTOR0 : Register<0x190070, 32, true> + { + struct Rcs0 : Bitfield<0, 1> { }; + }; + + /* p. 1077 */ + struct GEN12_RENDER_COPY_INTR_ENABLE : Register<0x190030, 32> + { + struct Render_enable : Bitfield<16, 16> { }; + struct Copy_enable : Bitfield< 0, 16> { }; + }; + + /* + * IHD-OS-TGL-Vol 2d-12.21 p. 818 ff + */ + struct GEN12_RENDER_INTR_VEC : Genode::Register<16> + { + struct Catastrophic_error : Bitfield<15, 1> { }; + struct Eu_restart : Bitfield<14, 1> { }; + struct Context_stall : Bitfield<13, 1> { }; + struct Cs_wait_on_semaphore : Bitfield<11, 1> { }; + struct Cs_ctx_switch_interrupt : Bitfield< 8, 1> { }; + struct Legacy_page_fault_error : Bitfield< 7, 1> { }; + struct Cs_watchdog_counter_expired : Bitfield< 6, 1> { }; + struct Cs_pipe_control_notify : Bitfield< 4, 1> { }; + struct Cs_error_interrupt : Bitfield< 3, 1> { }; + struct Cs_mi_user_interrupt : Bitfield< 0, 1> { }; + }; + /************************** ** Page-table registers ** **************************/ @@ -696,6 +756,36 @@ class Igd::Mmio : public Platform::Device::Mmio struct ELEM_DESCRIPTOR1 : Register<0x4400, 32> { }; struct ELEM_DESCRIPTOR2 : Register<0x4404, 32> { }; + /** + * GEN9+ GPM unit lx 5.15 + */ + struct CTC_MODE : Register<0xa26c, 32> + { + struct Source_divide_logic : Bitfield<0, 1> { }; + }; + + /** + * GEN8+ RPM unit + */ + struct RPM_CONFIG0 : Register<0x0d00, 32> + { + struct Ctc_shift : Bitfield<1, 2> { }; + struct Crystal_clock_frequency : Bitfield<3, 3> { }; + + static uint32_t clock_frequency(Crystal_clock_frequency::access_t freq) + { + switch (freq) { + case 0: return 24'000'000; + case 1: return 19'200'000; + case 2: return 38'400'000; + case 3: return 25'000'000; + default: + Genode::error("Unknown crystal clock frequency: ", freq); + return 0; + } + } + }; + /** * Forcewake for GEN9 & GEN10, lx 5.13 */ @@ -823,6 +913,28 @@ class Igd::Mmio : public Platform::Device::Mmio */ struct EU_DISABLE : Register_array<0x9134, 32, 12, 8> { }; + /* + * IHD-OS-TGL-Vol 2c-12.21 part2 p. 81 + */ + struct MIRROR_EU_DISABLE0 : Register<0x9134, 32> + { + struct Disabled : Bitfield<0, 8> { }; + }; + + /* + * IHD-OS-TGL-Vol 2c-12.2 part 2 p.98 + */ + struct MIRROR_GT_SLICE_EN : Register<0x9138, 32> + { + struct Enabled : Bitfield<0, 8> { }; + }; + + /* + * IHD-OS-TGL-Vol 2c-12.21 part2 p.97 + */ + struct MIRROR_GT_DSS_ENABLE : Register<0x913c, 32> { }; + + /* * IHD-OS-BDW-Vol 2c-11.15 p. 611 ff. */ @@ -835,6 +947,7 @@ class Igd::Mmio : public Platform::Device::Mmio struct Fence_valid : Bitfield< 0, 1> { }; }; + /* * IHD-OS-BDW-Vol 12-11.15 p. 5 */ @@ -845,6 +958,7 @@ class Igd::Mmio : public Platform::Device::Mmio ** EXECLIST registers ** ************************/ + /* GEN8-11 */ /* * IHD-OS-BDW-Vol 2c-11.15 p. 435 */ @@ -895,6 +1009,34 @@ class Igd::Mmio : public Platform::Device::Mmio struct EXECLIST_SUBMITPORT_VCSUNIT1 : EXECLIST_SUBMITPORT_BASE<0x1C000> { }; struct EXECLIST_SUBMITPORT_BSCUNIT : EXECLIST_SUBMITPORT_BASE<0x22000> { }; + /* GEN12 */ + template + struct GEN12_EXECLIST_STATUS_BASE : Register + { + using B = Register; + struct Execution_queue_invalid : B::template Bitfield<0, 1> { }; + }; + + struct GEN12_EXECLIST_STATUS_RSCUNIT : GEN12_EXECLIST_STATUS_BASE<0x02000> { }; + + /* + * IHD-OS-TGL-Vol 2c-12.21 p. 896 + */ + struct GEN12_EXECLIST_SQ_CONTENTS_RSCUNIT : Register_array<0x2510, 32, 16, 32> { }; + + /* + * IHD-OS-TGL-Vol 2c-12.21 p.891 + */ + template + struct GEN12_EXECLIST_CONTROL_BASE : Register + { + using B = Register; + /* load submission queue into exec queue */ + struct Load : B::template Bitfield<0, 1> { }; + }; + + struct GEN12_EXECLIST_CONTROL_RSCUNIT : GEN12_EXECLIST_CONTROL_BASE<0x02000> { }; + /* * IHD-OS-BDW-Vol 2c-11.15 p. 266 ff. * IHD-OS-BDW-Vol 6-11.15 p. 19 ff. @@ -1023,7 +1165,6 @@ class Igd::Mmio : public Platform::Device::Mmio using namespace Genode; while (read()) { - log(__func__, " ", __LINE__, " wait ", Hex(read())); _delayer.usleep(500 * 1000); _fw_enable_wa(); @@ -1048,7 +1189,6 @@ class Igd::Mmio : public Platform::Device::Mmio using namespace Genode; while (read()) { - log(__func__, " ", __LINE__, " wait ", Hex(read())); _delayer.usleep(500 * 1000); } @@ -1059,12 +1199,7 @@ class Igd::Mmio : public Platform::Device::Mmio _delayer.usleep(100 * 1000); - log(__func__, " ", __LINE__, " ", - Genode::Hex(read()), " ", - Genode::Hex(read())); - while (!(read())) { - log(__func__, " ", __LINE__, " wait ", Hex(read())); _delayer.usleep(500 * 1000); } @@ -1092,8 +1227,6 @@ class Igd::Mmio : public Platform::Device::Mmio write(v); while (read()) { - Genode::log(__func__, " ", __LINE__, " wait ", - Genode::Hex(read())); _delayer.usleep(500 * 1000); } } @@ -1119,6 +1252,12 @@ class Igd::Mmio : public Platform::Device::Mmio /* TODO DE intr handling (p. 363) */ } + void _intr_reset_gen12() + { + write(0); + write_post(0xffffffff); + } + /** * Enable interrupts */ @@ -1201,6 +1340,16 @@ class Igd::Mmio : public Platform::Device::Mmio write_post(1); } + void _intr_enable_gen12() + { + GEN12_RENDER_INTR_VEC::access_t vec { 0 }; + GEN12_RENDER_INTR_VEC::Cs_mi_user_interrupt::set(vec, 1); + GEN12_RENDER_INTR_VEC::Cs_ctx_switch_interrupt::set(vec, 1); + write(vec); + write_post(~vec); + write(1); + } + /** * Disable Render P-states */ @@ -1421,6 +1570,31 @@ class Igd::Mmio : public Platform::Device::Mmio write(v); } + uint32_t _clock_frequency_gen12() + { + uint32_t freq { 0 }; + + /* TIMESTAMP_OVERRIDE when source divide logic */ + if (read()) { + Genode::error("clock frequency: source divide not implemented"); + } + /* RMP_CONFIG when crystal logic */ + else { + freq = RPM_CONFIG0::clock_frequency( + read()); + + Genode::log("clock frequency: ", freq, " Hz from crystal logic"); + + /* + * Shift by Ctc_shift for lowest timestamp counter because counter may + * not increment at every cycle + */ + freq >>= 3 - read(); + } + + return freq; + } + public: Mmio(Platform::Device & device, Genode::Env & env) @@ -1433,6 +1607,15 @@ class Igd::Mmio : public Platform::Device::Mmio (void)read(); } + + uint32_t clock_frequency(unsigned const generation) + { + if (generation >= 11) + return _clock_frequency_gen12(); + + return 0; + } + void forcewake_gen8_enable() { _fw_enable(FORCEWAKE_ID_RENDER); } void forcewake_gen8_disable() { _fw_disable(FORCEWAKE_ID_RENDER); } @@ -1440,12 +1623,12 @@ class Igd::Mmio : public Platform::Device::Mmio { _fw_enable_gt(); _fw_enable_render(); - _fw_enable_media(); + //_fw_enable_media(); } void forcewake_gen9_disable() { - _fw_disable_media(); + //_fw_disable_media(); _fw_disable_render(); _fw_disable_gt(); } @@ -1457,6 +1640,7 @@ class Igd::Mmio : public Platform::Device::Mmio forcewake_gen8_enable(); return; case 9: + case 12: forcewake_gen9_enable(); return; default: @@ -1470,7 +1654,8 @@ class Igd::Mmio : public Platform::Device::Mmio case 8: forcewake_gen8_disable(); return; - case 9: + case 9: [[fallthrough]]; + case 12: forcewake_gen9_disable(); return; default: @@ -1486,7 +1671,10 @@ class Igd::Mmio : public Platform::Device::Mmio return; case 9: reset_gen9(); - return; + break; + case 12: + reset_gen12(); + break;; default: Genode::error(__func__, " unsupported generation ", generation); } @@ -1516,29 +1704,101 @@ class Igd::Mmio : public Platform::Device::Mmio _set_page_attributes(); } + void reset_gen12() + { + _intr_reset_gen12(); + _fw_reset_gen9(); + forcewake_gen9_enable(); + _reset_device(); + _reset_fences(); + + _disable_nde_handshake(); + _set_page_attributes(); + } + void init() { _disable_rps(); _enable_execlist(); } - void enable_intr() - { + void enable_intr(unsigned const generation) + { write(0xffffff00); - _intr_enable(); + if (generation < 11) + _intr_enable(); + else + _intr_enable_gen12(); } - void disable_master_irq() + void disable_master_irq(unsigned const generation) { - write_post(0); + if (generation < 11) + write_post(0); + else + write(0); } - void enable_master_irq() + void enable_master_irq(unsigned const generation) { - write_post(1); + if (generation < 11) + write_post(1); + else + write(1); } + bool render_irq(unsigned const generation) + { + if (generation < 11) + return read() == 1; + else { + if (read() == 1 && + read() == 1) + return true; + } + return false; + } + + GEN12_RENDER_INTR_VEC::access_t read_irq_vector(unsigned const generation) + { + GEN12_RENDER_INTR_VEC::access_t vec = 0; + if (generation < 11) { + vec = read(); + } else { + write(1); + + try { + wait_for(Attempts(50), Microseconds(500), _delayer, + GEN12_INTR_IDENTITY_REG0::Valid::Equal(1)); + } catch (Polling_timeout) { + Genode::error(__func__, " IRQ vector not valid"); + return vec; + } + vec = read(); + write(1); + } + + return vec; + }; + + void clear_render_irq(unsigned const generation, Genode::uint16_t v) + { + if (generation < 11) + write_post(v); + else + write(1); + } + + bool display_irq(unsigned const generation) + { + if (generation < 11) + return read() != 0; + else + return read() == 1; + } + + void flush_gfx_tlb() { _gfx_flush_cntl(); } void clear_errors() diff --git a/repos/os/src/drivers/gpu/intel/ppgtt_allocator.h b/repos/os/src/drivers/gpu/intel/ppgtt_allocator.h index 9860aaee05..e661b613ea 100644 --- a/repos/os/src/drivers/gpu/intel/ppgtt_allocator.h +++ b/repos/os/src/drivers/gpu/intel/ppgtt_allocator.h @@ -73,9 +73,9 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator try { ds = _backend.alloc(alloc_size); } - catch (Genode::Out_of_ram) { return Alloc_error::OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return Alloc_error::OUT_OF_CAPS; } - catch (...) { return Alloc_error::DENIED; } + catch (Gpu::Session::Out_of_ram) { throw; } + catch (Gpu::Session::Out_of_caps) { throw; } + catch (...) { return Alloc_error::DENIED; } Alloc_error alloc_error = Alloc_error::DENIED;