From 6b1f1794c452334d57021ba85d14eaad772c8a79 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 10 Aug 2021 13:38:46 +0200 Subject: [PATCH] gpu/intel: add gen9 forcewake support issue #4254 --- repos/os/src/drivers/gpu/intel/main.cc | 19 +- repos/os/src/drivers/gpu/intel/mmio.h | 291 +++++++++++++++++++++++-- 2 files changed, 283 insertions(+), 27 deletions(-) diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index 7e5bd96cb5..c63586a6bf 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -912,11 +912,10 @@ struct Igd::Device void _device_reset_and_init() { - _mmio.reset(); + _mmio.reset(_info.generation); _mmio.clear_errors(); _mmio.init(); _mmio.enable_intr(); - _mmio.forcewake_enable(); } /** @@ -976,14 +975,14 @@ struct Igd::Device _clock_gating(); - _mmio->dump(); - _mmio->context_status_pointer_dump(); + _mmio.dump(); + _mmio.context_status_pointer_dump(); /* read out slice, subslice, EUs information depending on platform */ if (_info.platform == Device_info::Platform::BROADWELL) { enum { SUBSLICE_MAX = 3 }; _subslice_mask.value = (1u << SUBSLICE_MAX) - 1; - _subslice_mask.value &= ~_mmio->read(); + _subslice_mask.value &= ~_mmio.read(); for (unsigned i=0; i < SUBSLICE_MAX; i++) if (_subslice_mask.value & (1u << i)) @@ -995,7 +994,7 @@ struct Igd::Device if (_info.generation == 9) { enum { SUBSLICE_MAX = 4 }; _subslice_mask.value = (1u << SUBSLICE_MAX) - 1; - _subslice_mask.value &= ~_mmio->read(); + _subslice_mask.value &= ~_mmio.read(); for (unsigned i=0; i < SUBSLICE_MAX; i++) if (_subslice_mask.value & (1u << i)) @@ -1005,13 +1004,13 @@ struct Igd::Device } else Genode::error("unsupported platform ", (int)_info.platform); - _timer.sigh(_watchdog_timeout_sigh); + _resources.timer().sigh(_watchdog_timeout_sigh); } void _clock_gating() { if (_info.platform == Device_info::Platform::KABYLAKE) { - _mmio->kbl_clock_gating(); + _mmio.kbl_clock_gating(); } else Genode::warning("no clock gating"); } @@ -1024,7 +1023,7 @@ struct Igd::Device Genode::error("wrong eu_total calculation"); } - _slice_mask.value = _mmio->read(); + _slice_mask.value = _mmio.read(); unsigned eu_total = 0; @@ -1043,7 +1042,7 @@ struct Igd::Device if (!(_slice_mask.value & (1u << slice))) continue; - auto const disabled = _mmio->read(disable_byte); + auto const disabled = _mmio.read(disable_byte); for (unsigned b = 0; b < 8; b++) { if (disabled & (1u << b)) diff --git a/repos/os/src/drivers/gpu/intel/mmio.h b/repos/os/src/drivers/gpu/intel/mmio.h index a3e3acaae2..92204da02b 100644 --- a/repos/os/src/drivers/gpu/intel/mmio.h +++ b/repos/os/src/drivers/gpu/intel/mmio.h @@ -698,6 +698,47 @@ class Igd::Mmio : public Genode::Mmio struct ELEM_DESCRIPTOR1 : Register<0x4400, 32> { }; struct ELEM_DESCRIPTOR2 : Register<0x4404, 32> { }; + /** + * Forcewake for GEN9 & GEN10, lx 5.13 + */ + struct FORCEWAKE_GT_GEN9 : Register<0x0a188, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + struct FORCEWAKE_MEDIA_GEN9 : Register<0x0a270, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + struct FORCEWAKE_RENDER_GEN9 : Register<0x0a278, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + + struct FORCEWAKE_GEN9_RENDER_ACK : Register<0x000D84, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + struct FORCEWAKE_GEN9_MEDIA_ACK : Register<0x000D88, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + struct FORCEWAKE_GEN9_GT_ACK : Register<0x130044, 32> { + struct Fallback_kernel_mask : Bitfield<31, 1> { }; + struct Kernel_mask : Bitfield<16, 1> { }; + struct Fallback_kernel : Bitfield<15, 1> { }; + struct Kernel : Bitfield< 0, 1> { }; + }; + /* * IHD-OS-BDW-Vol 2c-11.15 p. 703 * @@ -722,20 +763,32 @@ class Igd::Mmio : public Genode::Mmio { using B = Register; - struct Mask_bits : B::template Bitfield<16, 15> { }; + struct Mask_bits : B::template Bitfield<16, 16> { }; struct Ready_for_reset : B::template Bitfield< 1, 1> { }; struct Request_reset : B::template Bitfield< 0, 1> { }; }; + template + struct MI_MODE_CTRL_BASE : Register + { + using F = Register; + + struct Rings_idle : F::template Bitfield< 9, 1> { }; + struct Stop_rings_mask : F::template Bitfield<16 + 8, 1> { }; + struct Stop_rings : F::template Bitfield< 8, 1> { }; + }; + /* * IHD-OS-BDW-Vol 2c-11.15 p. 288 */ - struct CS_RESET_CTRL : RESET_CTRL_BASE<0x02000> { }; + struct CS_RESET_CTRL : RESET_CTRL_BASE <0x02000> { }; + struct CS_MI_MODE_CTRL : MI_MODE_CTRL_BASE<0x02000> { }; /* * IHD-OS-BDW-Vol 2c-11.15 p. 165 */ - struct BCS_RESET_CTRL : RESET_CTRL_BASE<0x22000> { }; + struct BCS_RESET_CTRL : RESET_CTRL_BASE <0x22000> { }; + struct BCS_MI_MODE_CTRL : MI_MODE_CTRL_BASE<0x22000> { }; /* * IHD-OS-BDW-Vol 2c-11.15 p. 609 ff. @@ -885,7 +938,7 @@ class Igd::Mmio : public Genode::Mmio Mmio::Delayer &_delayer; - void _fw_reset() + void _fw_reset_gen8() { using namespace Genode; @@ -941,6 +994,107 @@ class Igd::Mmio : public Genode::Mmio } } + void _fw_reset_gen9() + { + write_post(FORCEWAKE_MT::RESET); + write_post(FORCEWAKE_MT::RESET); + write_post(FORCEWAKE_MT::RESET); + } + + /** + * Set forcewake state, i.e., prevent from powering down + */ + void _fw_enable_media() { + _fw_enable(); } + + void _fw_enable_gt() { + _fw_enable(); } + + void _fw_enable_render() { + _fw_enable(); } + + template + void _fw_enable() + { + using namespace Genode; + + while (read()) { + log(__func__, " ", __LINE__, " wait ", Hex(read())); + _delayer.usleep(500 * 1000); + + _fw_enable_wa(); + } + + typename REG::access_t v = 0; + REG::Kernel_mask::set(v, 1); + REG::Kernel ::set(v, 1); + write(v); + + try { + wait_for(Attempts(50), Microseconds(1000), _delayer, + typename REG_ACK::Equal(1)); + } catch (Polling_timeout) { + error(__func__, " could not enable force-wake"); + } + } + + template + void _fw_enable_wa() + { + using namespace Genode; + + while (read()) { + log(__func__, " ", __LINE__, " wait ", Hex(read())); + _delayer.usleep(500 * 1000); + } + + typename REG::access_t v_set = 0; + REG::Fallback_kernel_mask::set(v_set, 1); + REG::Fallback_kernel ::set(v_set, 1); + write(v_set); + + _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); + } + + typename REG::access_t v_clear = 0; + REG::Fallback_kernel_mask::set(v_clear, 1); + REG::Fallback_kernel ::set(v_clear, 0); + write(v_clear); + } + + void _fw_disable_media() { + _fw_disable(); } + + void _fw_disable_gt() { + _fw_enable(); } + + void _fw_disable_render() { + _fw_disable(); } + + template + void _fw_disable() + { + typename REG::access_t v = 0; + REG::Kernel_mask::set(v, 1); + REG::Kernel ::set(v, 0); + write(v); + + while (read()) { + Genode::log(__func__, " ", __LINE__, " wait ", + Genode::Hex(read())); + _delayer.usleep(500 * 1000); + } + } + + /** * Reset interrupts */ @@ -1139,12 +1293,45 @@ class Igd::Mmio : public Genode::Mmio write(v >> 32); } + /** + * Stop engine + */ + template + bool _stop_engine() + { + auto mi_mode = read(); + + unsigned loop = 0; + + while (loop < 10 && !(REG_MI_MODE::Rings_idle::get(mi_mode))) { + REG_MI_MODE::Stop_rings_mask::set(mi_mode, 1); + REG_MI_MODE::Stop_rings::set(mi_mode, 1); + write_post(mi_mode); + + _delayer.usleep(10 * loop); + + mi_mode = read(); + + loop ++; + } + + if (!(REG_MI_MODE::Rings_idle::get(mi_mode))) { + Genode::error("could not stop engine"); + return false; + } + + return true; + } + /** * Reset engine */ - template + template bool _reset_engine() { + if (!_stop_engine()) + return false; + typename REG::access_t v = 0; REG::Mask_bits::set(v, 1); REG::Request_reset::set(v, 1); @@ -1156,6 +1343,7 @@ class Igd::Mmio : public Genode::Mmio Genode::error("could not reset engine"); return false; } + return true; } @@ -1167,18 +1355,23 @@ class Igd::Mmio : public Genode::Mmio bool _reset_engine(unsigned id) { switch (id) { - case RCS_ID: return _reset_engine(); - case BCS_ID: return _reset_engine(); + case RCS_ID: return _reset_engine(); + case BCS_ID: return _reset_engine(); default: return true; } } bool _reset_engines() { + bool reset_failed = false; + for (int i = 0; i < NUM_ENGINES; i++) { - if (!_reset_engine(i)) { return false; } + if (!_reset_engine(i)) { + reset_failed = true; + Genode::warning("engine ", i, " reset failed"); + } } - return true; + return !reset_failed; } /** @@ -1186,8 +1379,6 @@ class Igd::Mmio : public Genode::Mmio */ void _reset_device() { - _fw_enable(FORCEWAKE_ID_RENDER); - bool res = _reset_engines(); if (!res) { Genode::warning("cannot reset device, engines not ready"); @@ -1201,8 +1392,6 @@ class Igd::Mmio : public Genode::Mmio } catch (Mmio::Polling_timeout) { Genode::error("resetting device failed"); } - - _fw_disable(FORCEWAKE_ID_RENDER); } /** @@ -1240,18 +1429,86 @@ class Igd::Mmio : public Genode::Mmio (void)read(); } - void forcewake_enable() { _fw_enable(FORCEWAKE_ID_RENDER); } - void forcewake_disable() { _fw_disable(FORCEWAKE_ID_RENDER); } + void forcewake_gen8_enable() { _fw_enable(FORCEWAKE_ID_RENDER); } + void forcewake_gen8_disable() { _fw_disable(FORCEWAKE_ID_RENDER); } - void reset() + void forcewake_gen9_enable() + { + _fw_enable_gt(); + _fw_enable_render(); + _fw_enable_media(); + } + + void forcewake_gen9_disable() + { + _fw_disable_media(); + _fw_disable_render(); + _fw_disable_gt(); + } + + void forcewake_enable(unsigned const generation) + { + switch (generation) { + case 8: + forcewake_gen8_enable(); + return; + case 9: + forcewake_gen9_enable(); + return; + default: + Genode::error(__func__, " unsupported generation ", generation); + } + } + + void forcewake_disable(unsigned const generation) + { + switch (generation) { + case 8: + forcewake_gen8_disable(); + return; + case 9: + forcewake_gen9_disable(); + return; + default: + Genode::error(__func__, " unsupported generation ", generation); + } + } + + void reset(unsigned const generation) + { + switch (generation) { + case 8: + reset_gen8(); + return; + case 9: + reset_gen9(); + return; + default: + Genode::error(__func__, " unsupported generation ", generation); + } + } + + void reset_gen8() { _intr_reset(); + _fw_reset_gen8(); + forcewake_gen8_enable(); _reset_device(); - _fw_reset(); _reset_fences(); _disable_nde_handshake(); + _set_page_attributes(); + } + void reset_gen9() + { + _intr_reset(); + _fw_reset_gen9(); + forcewake_gen9_enable(); + _reset_device(); + _reset_fences(); + + _disable_nde_handshake(); _set_page_attributes(); }