| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef REGISTERS_H |
| #define REGISTERS_H |
| |
| #include <lib/magma/util/short_macros.h> |
| #include <lib/magma/util/utils.h> |
| |
| #include <bitset> |
| #include <vector> |
| |
| #include "device_id.h" |
| #include "hwreg/bitfields.h" |
| #include "msd_intel_register_io.h" |
| #include "types.h" |
| |
| namespace registers { |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.733 |
| class GmchGraphicsControl { |
| public: |
| static constexpr uint32_t kOffset = 0x50; |
| static constexpr uint32_t kGttSizeShift = 6; |
| static constexpr uint32_t kGttSizeMask = 0x3; |
| |
| static uint32_t gtt_size(uint32_t val) { |
| unsigned int size = (val >> kGttSizeShift) & kGttSizeMask; |
| return (size == 0) ? 0 : (1 << size) * 1024 * 1024; |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.712 |
| class HardwareStatusPageAddress { |
| public: |
| static constexpr uint32_t kOffset = 0x80; |
| |
| static void write(MsdIntelRegisterIo* reg_io, uint32_t mmio_base, uint32_t gtt_addr) { |
| DASSERT(magma::is_page_aligned(gtt_addr)); |
| reg_io->Write32(gtt_addr, mmio_base + kOffset); |
| reg_io->mmio()->PostingRead32(mmio_base + kOffset); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.500 |
| class PatIndex { |
| public: |
| static constexpr uint32_t kOffsetLow = 0x40E0; |
| static constexpr uint32_t kOffsetHigh = 0x40E4; |
| |
| static constexpr uint8_t kUncacheable = 0; |
| static constexpr uint8_t kWriteCombining = 1; |
| static constexpr uint8_t kWriteThrough = 2; |
| static constexpr uint8_t kWriteBack = 3; |
| static constexpr uint8_t kMemTypeMask = 0x3; |
| |
| static constexpr uint8_t kEllc = 0; |
| static constexpr uint8_t kLlc = 1; |
| static constexpr uint8_t kLlcEllc = 2; |
| static constexpr uint8_t kTargetCacheMask = 3; |
| |
| static constexpr uint8_t kLruAgeFromUncore = 0; |
| static constexpr uint8_t kLruAgeZero = 1; |
| static constexpr uint8_t kLruAgeNoChange = 2; |
| static constexpr uint8_t kLruAgeThree = 3; |
| static constexpr uint8_t kLruAgeMask = 0x3; |
| |
| static void write(MsdIntelRegisterIo* reg_io, uint64_t val) { |
| reg_io->Write32(static_cast<uint32_t>(val), kOffsetLow); |
| reg_io->Write32(static_cast<uint32_t>(val >> 32), kOffsetHigh); |
| } |
| |
| static uint64_t ppat(unsigned int index, uint8_t lru_age, uint8_t target_cache, |
| uint8_t mem_type) { |
| DASSERT((lru_age & ~kLruAgeMask) == 0); |
| DASSERT((target_cache & ~kTargetCacheMask) == 0); |
| DASSERT((mem_type & ~kMemTypeMask) == 0); |
| uint64_t ppat = (lru_age << 4) | (target_cache << 2) | mem_type; |
| return ppat << (index * 8); |
| } |
| }; |
| |
| // PAT_INDEX |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part2-rev2_1.pdf |
| // p.645 |
| class PatIndexGen12 { |
| public: |
| static constexpr uint32_t kOffset = 0x4800; |
| static constexpr uint32_t kIndexCount = 8; |
| |
| enum MemType { UNCACHEABLE = 0, WRITE_COMBINING = 1, WRITE_THROUGH = 2, WRITE_BACK = 3 }; |
| |
| static void write(MsdIntelRegisterIo* register_io, uint32_t index, MemType type) { |
| DASSERT(index < kIndexCount); |
| register_io->Write32(type, kOffset + index * sizeof(uint32_t)); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.438 |
| // and intel-gfx-prm-osrc-bdw-vol02d-commandreference-structures_3.pdf p.107 |
| // Note: this register exists in all hardware but ExeclistSubmitQueue is used from gen12. |
| class ExeclistSubmitPort { |
| public: |
| static constexpr uint32_t kSubmitOffset = 0x230; |
| static constexpr uint32_t kStatusOffset = 0x234; |
| |
| static uint64_t context_descriptor(gpu_addr_t gpu_addr, uint32_t context_id, bool ppgtt_enable) { |
| constexpr uint32_t kValid = 1; |
| constexpr uint32_t kLegacyMode48bitPpgtt = 3 << 3; |
| constexpr uint32_t kLegacyModePpgttEnable = 1 << 8; |
| constexpr uint32_t kContextIdShift = 32; |
| |
| uint64_t desc = gpu_addr; |
| desc |= kValid; |
| desc |= kLegacyMode48bitPpgtt; |
| if (ppgtt_enable) |
| desc |= kLegacyModePpgttEnable; |
| desc |= static_cast<uint64_t>(context_id) << kContextIdShift; |
| return desc; |
| } |
| |
| static void write(MsdIntelRegisterIo* reg_io, uint32_t mmio_base, uint64_t descriptor1, |
| uint64_t descriptor0) { |
| uint32_t desc[4]{magma::upper_32_bits(descriptor1), magma::lower_32_bits(descriptor1), |
| magma::upper_32_bits(descriptor0), magma::lower_32_bits(descriptor0)}; |
| |
| // The last write triggers the context load. |
| reg_io->Write32(desc[0], mmio_base + kSubmitOffset); |
| reg_io->Write32(desc[1], mmio_base + kSubmitOffset); |
| reg_io->Write32(desc[2], mmio_base + kSubmitOffset); |
| reg_io->Write32(desc[3], mmio_base + kSubmitOffset); |
| |
| reg_io->mmio()->PostingRead32(mmio_base + kStatusOffset); |
| } |
| }; |
| |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.896 |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02d-commandreference-structures_0.pdf |
| // p.275 |
| class ExeclistSubmitQueue { |
| public: |
| static constexpr uint32_t kOffset = 0x510; |
| |
| enum EngineType { |
| RENDER = 0, |
| VIDEO = 1, |
| }; |
| |
| static constexpr uint64_t context_descriptor(EngineType type, uint32_t instance, |
| uint32_t context_id, gpu_addr_t gpu_addr) { |
| constexpr uint32_t kValid = 1; |
| constexpr uint32_t kLegacyMode48bitPpgtt = 3 << 3; |
| constexpr uint32_t kLegacyModePpgttEnable = 1 << 8; |
| constexpr uint64_t kContextIdShift = 37; |
| constexpr uint64_t kEngineClassShift = 61; |
| constexpr uint64_t kEngineInstanceShift = 48; |
| |
| DASSERT(gpu_addr < (1ul << 32) && (gpu_addr & 0xFFF) == 0); |
| DASSERT(context_id < (1u << 11)); |
| DASSERT(instance < (1u << 6)); |
| |
| uint64_t desc = gpu_addr; |
| desc |= kValid | kLegacyMode48bitPpgtt | kLegacyModePpgttEnable; |
| desc |= static_cast<uint64_t>(context_id) << kContextIdShift; |
| desc |= static_cast<uint64_t>(type) << kEngineClassShift; |
| desc |= static_cast<uint64_t>(instance) << kEngineInstanceShift; |
| return desc; |
| } |
| |
| // May be expanded up to 8 descriptors at consecutive addresses. |
| static void write(MsdIntelRegisterIo* reg_io, uint32_t mmio_base, uint64_t descriptor) { |
| reg_io->Write32(magma::lower_32_bits(descriptor), mmio_base + kOffset); |
| reg_io->Write32(magma::upper_32_bits(descriptor), mmio_base + kOffset + sizeof(uint32_t)); |
| } |
| }; |
| |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf |
| // p.616 |
| class ExeclistStatusGen9 { |
| public: |
| static constexpr uint32_t kOffset = 0x234; |
| static constexpr uint32_t kExeclistCurrentPointerShift = 0; |
| static constexpr uint32_t kExeclistWritePointerShift = 1; |
| static constexpr uint32_t kExeclistQueueFullShift = 2; |
| |
| static uint64_t read(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| // Hmm 64-bit read would be better but kOffset is not 64bit aligned |
| uint64_t status = reg_io->Read32(mmio_base + kOffset + 4); |
| status = (status << 32) | reg_io->Read32(mmio_base + kOffset); |
| return status; |
| } |
| |
| static uint32_t execlist_current_pointer(uint64_t status) { |
| return (status >> kExeclistCurrentPointerShift) & 0x1; |
| } |
| |
| static uint32_t execlist_write_pointer(uint64_t status) { |
| return (status >> kExeclistWritePointerShift) & 0x1; |
| } |
| |
| static bool execlist_queue_full(uint64_t status) { |
| return (status >> kExeclistQueueFullShift) & 0x1; |
| } |
| }; |
| |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.892 |
| class ExeclistStatusGen12 : public hwreg::RegisterBase<ExeclistStatusGen12, uint64_t> { |
| public: |
| DEF_FIELD(63, 32, context_id); |
| DEF_BIT(30, pending_load); |
| DEF_BIT(27, arb_enable); |
| DEF_FIELD(26, 12, last_context_switch_reason); |
| DEF_FIELD(11, 8, active_context_offset); |
| DEF_BIT(7, active_context); |
| DEF_BIT(4, valid_exec_queue_dupe); |
| DEF_BIT(3, valid_exec_queue); |
| DEF_BIT(2, preempt_to_idle_pending); |
| DEF_BIT(1, two_pending_loads); |
| DEF_BIT(0, exec_queue_invalid); |
| |
| static auto GetAddr(uint32_t mmio_base) { |
| return hwreg::RegisterAddr<ExeclistStatusGen12>(mmio_base + 0x234); |
| } |
| }; |
| |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.889 |
| class ExeclistControl { |
| public: |
| static constexpr uint32_t kOffset = 0x550; |
| static constexpr uint32_t kLoad = 1; |
| |
| static void load(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| reg_io->Write32(kLoad, mmio_base + kOffset); |
| } |
| }; |
| |
| // intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part2_0.pdf p.748 |
| class Timestamp { |
| public: |
| static constexpr uint32_t kOffset = 0x358; |
| |
| static uint64_t read(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| uint64_t upper = reg_io->Read32(mmio_base + kOffset + 4); |
| uint64_t lower = reg_io->Read32(mmio_base + kOffset); |
| uint64_t upper_check = reg_io->Read32(mmio_base + kOffset + 4); |
| if (upper_check != upper) { |
| // Assume rollover |
| lower = reg_io->Read32(mmio_base + kOffset); |
| upper = upper_check; |
| } |
| return (upper << 32 | lower); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf p.1 |
| class ActiveHeadPointer { |
| public: |
| static constexpr uint32_t kOffset = 0x74; |
| static constexpr uint32_t kUpperOffset = 0x5C; |
| |
| static uint64_t read(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| uint64_t val = reg_io->Read32(mmio_base + kUpperOffset); |
| val = (val << 32) | reg_io->Read32(mmio_base + kOffset); |
| return val; |
| } |
| }; |
| |
| class RingbufferHead { |
| public: |
| static constexpr uint32_t kOffset = 0x34; |
| |
| static uint32_t read(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| return reg_io->Read32(mmio_base + kOffset); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf p.81 |
| class AllEngineFault : public hwreg::RegisterBase<AllEngineFault, uint32_t> { |
| public: |
| DEF_FIELD(14, 12, engine); |
| DEF_FIELD(10, 3, src); |
| DEF_FIELD(2, 1, type); |
| DEF_BIT(0, valid); |
| |
| enum Engine { |
| RCS = 0, |
| VCS1 = 1, |
| VCS2 = 2, |
| VBOX = 3, |
| BLT = 4, |
| }; |
| |
| static auto GetAddr(uint32_t device_id) { |
| if (DeviceId::is_gen12(device_id)) |
| return hwreg::RegisterAddr<AllEngineFault>(0xCEC4); |
| |
| DASSERT(DeviceId::is_gen9(device_id)); |
| return hwreg::RegisterAddr<AllEngineFault>(0x4094); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.446 |
| class FaultTlbReadData { |
| public: |
| static constexpr uint32_t kOffset0 = 0x4B10; |
| static constexpr uint32_t kOffset1 = 0x4B14; |
| static constexpr uint64_t kGgttCycle = 1ull << 36; |
| |
| static uint64_t read(MsdIntelRegisterIo* reg_io) { |
| return (static_cast<uint64_t>(reg_io->Read32(kOffset1)) << 32) | |
| static_cast<uint64_t>(reg_io->Read32(kOffset0)); |
| } |
| |
| static uint64_t addr(uint64_t val) { return (val & 0xFFFFFFFFFull) << 12; } |
| static bool is_ggtt(uint64_t val) { return val & kGgttCycle; } |
| }; |
| |
| class PowerGateEnable : public hwreg::RegisterBase<PowerGateEnable, uint32_t> { |
| public: |
| DEF_BIT(0, render_powergate_enable); |
| DEF_BIT(1, media_powergate_enable); |
| DEF_BIT(2, media_sampler_powergate_enable); |
| DEF_BIT(3, vcs0_hcp_powergate_enable); |
| DEF_BIT(4, vcs0_mfx_powergate_enable); |
| DEF_BIT(5, vcs1_hcp_powergate_enable); |
| DEF_BIT(6, vcs1_mfx_powergate_enable); |
| DEF_BIT(7, vcs2_hcp_powergate_enable); |
| DEF_BIT(8, vcs2_mfx_powergate_enable); |
| // More available hcp/mfx bits up to vcs7 |
| |
| static constexpr uint32_t kPowerGateAll = 0xFFFF'FFFF; |
| |
| static auto GetAddr() { return hwreg::RegisterAddr<PowerGateEnable>(0xA210); } |
| }; |
| |
| class CtcMode : public hwreg::RegisterBase<CtcMode, uint32_t> { |
| public: |
| bool source_is_crystal_clock() const { return source() == 0; } |
| |
| uint64_t freq_shift_bits() const { |
| DASSERT(ctc_shift() <= 3); |
| return 3 - ctc_shift(); |
| } |
| |
| uint64_t get_timestamp_frequency_gen9() const { return 24'000'000 >> freq_shift_bits(); } |
| |
| DEF_FIELD(2, 1, ctc_shift); |
| DEF_BIT(0, source); |
| |
| static auto GetAddr() { return hwreg::RegisterAddr<CtcMode>(0xA26C); } |
| }; |
| |
| // from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.493 |
| class ForceWakeRequest { |
| public: |
| static constexpr uint32_t kRenderOffset = 0xA278; |
| static constexpr uint32_t kGen9MediaOffset = 0xA270; |
| static constexpr uint32_t kGen12Vdbox0Offset = 0xA540; |
| |
| static void reset(MsdIntelRegisterIo* reg_io, uint32_t offset) { |
| write(reg_io, offset, 0xFFFF, 0); |
| } |
| |
| static void write(MsdIntelRegisterIo* reg_io, uint32_t offset, uint16_t mask, uint16_t val) { |
| uint32_t val32 = mask; |
| val32 = (val32 << 16) | val; |
| reg_io->Write32(val32, offset); |
| } |
| }; |
| |
| // from |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1-rev2_0.pdf |
| // p.243 |
| class RenderPerformanceConfig : public hwreg::RegisterBase<RenderPerformanceConfig, uint32_t> { |
| public: |
| uint64_t freq_shift_bits() const { |
| DASSERT(ctc_shift() <= 3); |
| return 3 - ctc_shift(); |
| } |
| |
| uint64_t get_timestamp_frequency_gen12() const { |
| switch (freq_select()) { |
| case 0: |
| return 24'000'000 >> freq_shift_bits(); |
| case 1: |
| return 19'200'000 >> freq_shift_bits(); |
| case 2: |
| return 38'400'000 >> freq_shift_bits(); |
| case 3: |
| return 25'000'000 >> freq_shift_bits(); |
| default: |
| DASSERT(false); |
| return 0; |
| } |
| } |
| |
| DEF_FIELD(5, 3, freq_select); |
| DEF_FIELD(2, 1, ctc_shift); |
| |
| static auto GetAddr() { return hwreg::RegisterAddr<RenderPerformanceConfig>(0xD00); } |
| }; |
| |
| class ForceWakeStatus : public hwreg::RegisterBase<ForceWakeStatus, uint32_t> { |
| public: |
| DEF_FIELD(15, 0, status); |
| |
| static constexpr uint32_t kRenderStatusOffset = 0xD84; |
| static constexpr uint32_t kGen9MediaStatusOffset = 0xD88; |
| static constexpr uint32_t kGen12Vdbox0StatusOffset = 0xD50; |
| |
| static ForceWakeStatus GetRender(MsdIntelRegisterIo* register_io) { |
| return hwreg::RegisterAddr<ForceWakeStatus>(kRenderStatusOffset).ReadFrom(register_io); |
| } |
| static ForceWakeStatus GetGen9Media(MsdIntelRegisterIo* register_io) { |
| return hwreg::RegisterAddr<ForceWakeStatus>(kGen9MediaStatusOffset).ReadFrom(register_io); |
| } |
| static ForceWakeStatus GetGen12Vdbox0(MsdIntelRegisterIo* register_io) { |
| return hwreg::RegisterAddr<ForceWakeStatus>(kGen12Vdbox0StatusOffset).ReadFrom(register_io); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.618 |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1034 |
| class GraphicsMode { |
| public: |
| static constexpr uint32_t kOffset = 0x29C; |
| static constexpr uint32_t kExeclistEnableGen9 = 1 << 15; |
| static constexpr uint32_t kExeclistDisableLegacyGen11 = 1 << 3; |
| |
| static uint32_t read(MsdIntelRegisterIo* reg_io, uint32_t mmio_base) { |
| return reg_io->Read32(mmio_base + kOffset); |
| } |
| |
| static void write(MsdIntelRegisterIo* reg_io, uint32_t mmio_base, uint16_t mask, uint16_t val) { |
| uint32_t val32 = mask; |
| val32 = (val32 << 16) | val; |
| reg_io->Write32(val32, mmio_base + kOffset); |
| reg_io->mmio()->PostingRead32(mmio_base + kOffset); |
| } |
| }; |
| |
| // from Intel-GFX-BSpec-NDA-SKL-20150707-b93797-r96240-Web register spec |
| class RenderPerformanceNormalFrequencyRequest { |
| public: |
| static constexpr uint32_t kOffset = 0xA008; |
| |
| static void write_frequency_request_gen9(MsdIntelRegisterIo* reg_io, uint32_t mhz) { |
| // Register in units of 16.66Mhz on skylake |
| uint32_t val = mhz * 3 / 50; |
| DASSERT(val <= 0x1ff); |
| reg_io->Write32(val << 23, kOffset); |
| } |
| |
| static uint32_t read(MsdIntelRegisterIo* reg_io) { |
| // Register in units of 16.66Mhz on skylake |
| return ((reg_io->Read32(kOffset) >> 23) & 0x1ff) * 50 / 3; |
| } |
| }; |
| |
| class RenderPerformanceStatus { |
| public: |
| static constexpr uint32_t kOffset = 0xA01C; |
| |
| // Returns frequency in MHz |
| static uint32_t read_current_frequency_gen9(MsdIntelRegisterIo* reg_io) { |
| // Register in units of 16.66Mhz on skylake |
| return (reg_io->Read32(kOffset) >> 23) * 50 / 3; |
| } |
| }; |
| |
| class RenderPerformanceStateCapability { |
| public: |
| static constexpr uint32_t kOffset = 0x140000 + 0x5998; |
| |
| // Returns frequency in Mhz |
| static uint32_t read_rp0_frequency(MsdIntelRegisterIo* register_io) { |
| // Register units are 50Mhz |
| return (register_io->Read32(kOffset) & 0xff) * 50; |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.741 |
| class ResetControl { |
| public: |
| static constexpr uint32_t kOffset = 0xd0; |
| static constexpr uint32_t kRequestResetBit = 0; |
| static constexpr uint32_t kReadyForResetBit = 1; |
| |
| static void request(MsdIntelRegisterIo* register_io, uint32_t mmio_base) { |
| register_io->Write32(((1 << kRequestResetBit) << 16) | (1 << kRequestResetBit), |
| mmio_base + kOffset); |
| } |
| |
| static bool ready_for_reset(MsdIntelRegisterIo* register_io, uint32_t mmio_base) { |
| return register_io->Read32(mmio_base + kOffset) & (1 << kReadyForResetBit); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.755 |
| class GraphicsDeviceResetControl { |
| public: |
| static constexpr uint32_t kOffset = 0x941C; |
| static constexpr uint32_t kRcsResetBit = 1; |
| static constexpr uint32_t kVcsResetBit = 2; |
| static constexpr uint32_t kVcs0ResetBitGen12 = 5; |
| |
| static void initiate_reset(MsdIntelRegisterIo* register_io, uint8_t bit) { |
| DASSERT(bit == kRcsResetBit || bit == kVcsResetBit || bit == kVcs0ResetBitGen12); |
| register_io->Write32((1 << bit), kOffset); |
| } |
| |
| static bool is_reset_complete(MsdIntelRegisterIo* register_io, uint8_t bit) { |
| DASSERT(bit == kRcsResetBit || bit == kVcsResetBit || bit == kVcs0ResetBitGen12); |
| return (register_io->Read32(kOffset) & (1 << bit)) == 0; |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.10 |
| class MasterInterruptControl { |
| public: |
| static constexpr uint32_t kOffset = 0x44200; |
| static constexpr uint32_t kRenderInterruptsPendingBitMask = 1 << 0; |
| static constexpr uint32_t kVideoInterruptsPendingBitMask = 1 << 2; |
| static constexpr uint32_t kDisplayEnginePipeAInterruptsPendingBit = 1 << 16; |
| static constexpr uint32_t kEnableBitMask = 1 << 31; |
| |
| static void write(MsdIntelRegisterIo* register_io, bool enable) { |
| register_io->Write32(enable ? kEnableBitMask : 0, kOffset); |
| } |
| static uint32_t read(MsdIntelRegisterIo* register_io) { return register_io->Read32(kOffset); } |
| }; |
| |
| class InterruptRegisterBase { |
| public: |
| enum MaskOp { MASK, UNMASK }; |
| |
| static constexpr uint32_t kUserBit = 1 << 0; |
| static constexpr uint32_t kPageFaultBit = 1 << 7; // Only for the Interrupt0 register. |
| static constexpr uint32_t kContextSwitchBit = 1 << 8; |
| |
| static void write(MsdIntelRegisterIo* register_io, uint32_t offset, bool set, |
| uint16_t upper_engine_bits, uint16_t lower_engine_bits) { |
| DASSERT(((upper_engine_bits | lower_engine_bits) & ~(kUserBit | kContextSwitchBit)) == 0); |
| uint32_t bits = upper_engine_bits; |
| bits = (bits << 16) | lower_engine_bits; |
| |
| uint32_t val = register_io->Read32(offset); |
| |
| val = set ? (val | bits) : (val & ~bits); |
| register_io->Write32(val, offset); |
| |
| register_io->mmio()->PostingRead32(offset); |
| } |
| }; |
| |
| class HardwareStatusMask : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x98; |
| |
| static void write(MsdIntelRegisterIo* register_io, uint32_t mmio_base, MaskOp op, uint16_t bits) { |
| InterruptRegisterBase::write(register_io, mmio_base + kOffset, op == MASK, |
| /*upper_engine_bits=*/0, bits); |
| } |
| }; |
| |
| // For GtInterrupt0 series the source bits correspond to RenderCS |
| // (BlitterCS in the upper 16 bits). |
| // intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf p.924 |
| class GtInterruptMask0 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x44304; |
| |
| static void mask_render(MsdIntelRegisterIo* register_io, MaskOp op, uint16_t bits) { |
| InterruptRegisterBase::write(register_io, kOffset, op == MASK, /*upper_engine_bits=*/0, bits); |
| } |
| }; |
| |
| class GtInterruptIdentity0 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x44308; |
| |
| static uint32_t read(MsdIntelRegisterIo* register_io) { return register_io->Read32(kOffset); } |
| |
| static void clear(MsdIntelRegisterIo* register_io, uint16_t bits) { |
| DASSERT((bits & ~(kUserBit | kContextSwitchBit)) == 0); |
| register_io->Write32(bits, kOffset); |
| } |
| }; |
| |
| class GtInterruptEnable0 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x4430C; |
| |
| static void enable_render(MsdIntelRegisterIo* register_io, bool enable, uint16_t bits) { |
| InterruptRegisterBase::write(register_io, kOffset, enable, /*upper_engine_bits=*/0, bits); |
| } |
| }; |
| |
| // For GtInterrupt1 series the source bits correspond to VideoCS |
| // (VideoCS2 in the upper 16 bits). |
| // intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf p.926 |
| class GtInterruptMask1 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x44314; |
| |
| static void mask_vcs0(MsdIntelRegisterIo* register_io, MaskOp op, uint16_t bits) { |
| InterruptRegisterBase::write(register_io, kOffset, op == MASK, /*upper_engine_bits=*/0, bits); |
| } |
| }; |
| |
| class GtInterruptIdentity1 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x44318; |
| |
| static uint32_t read(MsdIntelRegisterIo* register_io) { return register_io->Read32(kOffset); } |
| |
| static void clear(MsdIntelRegisterIo* register_io, uint16_t bits) { |
| DASSERT((bits & ~(kUserBit | kContextSwitchBit)) == 0); |
| register_io->Write32(bits, kOffset); |
| } |
| }; |
| |
| class GtInterruptEnable1 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x4431C; |
| |
| static void enable_vcs0(MsdIntelRegisterIo* register_io, bool enable, uint16_t bits) { |
| InterruptRegisterBase::write(register_io, kOffset, enable, /*upper_engine_bits=*/0, bits); |
| } |
| }; |
| |
| // GT_ENG_INTR_ENABLE |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1077 |
| // Upper: render, lower: copy (blitter) |
| class GtInterruptEnable0Gen12 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x190030; |
| |
| static void enable_render(MsdIntelRegisterIo* register_io, bool enable, uint16_t bits) { |
| write(register_io, kOffset, enable, bits, /*lower_engine_bits=*/0); |
| } |
| }; |
| |
| // GT_ENG_INTR_ENABLE |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1077 |
| // Upper: video decode, lower: video enhance |
| class GtInterruptEnable1Gen12 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x190034; |
| |
| static void enable_video_decode(MsdIntelRegisterIo* register_io, bool enable, uint16_t bits) { |
| write(register_io, kOffset, enable, bits, /*lower_engine_bits=*/0); |
| } |
| }; |
| |
| // GT_ENG_INTR_MASK |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1079 |
| // Upper: render, lower (reserved) |
| class GtInterruptMask0Gen12 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x190090; |
| |
| static void mask_render(MsdIntelRegisterIo* register_io, MaskOp op, uint16_t bits) { |
| write(register_io, kOffset, op == MASK, bits, /*lower_engine_bits=*/0); |
| } |
| }; |
| |
| // GT_ENG_INTR_MASK |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1079 |
| // Upper: vcs0, lower: vcs1 |
| class GtInterruptMask2Gen12 : public InterruptRegisterBase { |
| public: |
| static constexpr uint32_t kOffset = 0x1900A8; |
| |
| static void mask_vcs0(MsdIntelRegisterIo* register_io, MaskOp op, uint16_t bits) { |
| write(register_io, kOffset, op == MASK, bits, /*lower_engine_bits=*/0); |
| } |
| }; |
| |
| // GT_INTR_DW0 |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1088 |
| class GtInterruptStatus0Gen12 : public hwreg::RegisterBase<GtInterruptStatus0Gen12, uint32_t> { |
| public: |
| DEF_BIT(0, rcs0); |
| |
| static GtInterruptStatus0Gen12 Get(MsdIntelRegisterIo* reg_io) { |
| return hwreg::RegisterAddr<GtInterruptStatus0Gen12>(0x190018).ReadFrom(reg_io); |
| } |
| }; |
| |
| // GT_INTR_DW1 |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1090 |
| class GtInterruptStatus1Gen12 : public hwreg::RegisterBase<GtInterruptStatus1Gen12, uint32_t> { |
| public: |
| DEF_BIT(0, vcs0); |
| |
| static GtInterruptStatus1Gen12 Get(MsdIntelRegisterIo* reg_io) { |
| return hwreg::RegisterAddr<GtInterruptStatus1Gen12>(0x19001C).ReadFrom(reg_io); |
| } |
| }; |
| |
| // GT_INTR_IIR_SELECTOR |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1092 |
| class GtInterruptSelector0Gen12 { |
| public: |
| static constexpr uint32_t kOffset = 0x190070; |
| static constexpr uint32_t kRcs0Bit = 0x1; |
| |
| static void write_rcs0(MsdIntelRegisterIo* register_io) { |
| register_io->Write32(kRcs0Bit, kOffset); |
| } |
| }; |
| |
| // GT_INTR_IIR_SELECTOR |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1092 |
| class GtInterruptSelector1Gen12 { |
| public: |
| static constexpr uint32_t kOffset = 0x190074; |
| static constexpr uint32_t kVcs0Bit = 0x1; |
| |
| static void write_vcs0(MsdIntelRegisterIo* register_io) { |
| register_io->Write32(kVcs0Bit, kOffset); |
| } |
| }; |
| |
| // GT_INTR_IDENTITY |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part1_0.pdf |
| // p.1091 |
| class GtInterruptIdentityGen12 : public hwreg::RegisterBase<GtInterruptIdentityGen12, uint32_t> { |
| public: |
| DEF_BIT(31, data_valid); |
| DEF_FIELD(25, 20, instance_id); |
| DEF_FIELD(18, 16, class_id); |
| DEF_FIELD(15, 0, interrupt); |
| |
| bool SpinUntilValid(MsdIntelRegisterIo* register_io, std::chrono::microseconds timeout) { |
| auto start = std::chrono::steady_clock::now(); |
| |
| while (data_valid() == 0) { |
| ReadFrom(register_io); |
| if (std::chrono::duration<double, std::micro>(std::chrono::steady_clock::now() - start) >= |
| timeout) { |
| break; |
| } |
| } |
| |
| return data_valid(); |
| } |
| |
| void Clear(MsdIntelRegisterIo* register_io) { |
| set_reg_value(0).set_data_valid(1); |
| WriteTo(register_io); |
| } |
| |
| static auto GetBank0(MsdIntelRegisterIo* reg_io) { |
| return hwreg::RegisterAddr<GtInterruptIdentityGen12>(0x190060).ReadFrom(reg_io); |
| } |
| static auto GetBank1(MsdIntelRegisterIo* reg_io) { |
| return hwreg::RegisterAddr<GtInterruptIdentityGen12>(0x190064).ReadFrom(reg_io); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.764 |
| class MemoryObjectControlState { |
| public: |
| static constexpr uint32_t kGraphicsOffset = 0xC800; |
| static constexpr uint32_t kGlobalOffsetGen12 = 0x4000; |
| |
| static constexpr uint32_t kCacheabilityShift = 0; |
| static constexpr uint32_t kCacheShift = 2; |
| static constexpr uint32_t kLruManagementShift = 4; |
| |
| enum Cacheability { PAGETABLE = 0, UNCACHED, WRITETHROUGH, WRITEBACK }; |
| enum Cache { LLC = 1, LLC_ELLC = 2 }; |
| enum LruManagement { LRU_0 = 0, LRU_3 = 3 }; |
| |
| static constexpr uint32_t format(Cacheability cacheability, Cache cache, |
| LruManagement lru_management) { |
| return (lru_management << kLruManagementShift) | (cache << kCacheShift) | |
| (cacheability << kCacheabilityShift); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.1118 |
| class LncfMemoryObjectControlState { |
| public: |
| static constexpr uint32_t kOffset = 0xB020; |
| |
| static constexpr uint32_t kCacheabilityShift = 4; |
| |
| enum Cacheability { DIRECT = 0, UNCACHED, WRITETHROUGH, WRITEBACK }; |
| |
| static constexpr uint16_t format(Cacheability cacheability) { |
| return static_cast<uint16_t>(cacheability << kCacheabilityShift); |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.403 |
| class Fuse2ControlDwordMirror { |
| public: |
| static constexpr uint32_t kOffset = 0x9120; |
| |
| static constexpr uint32_t kSliceEnableShift = 25; |
| static constexpr uint32_t kSliceEnableMask = 0x7 << kSliceEnableShift; |
| static constexpr uint32_t kSubsliceDisableShift = 20; |
| static constexpr uint32_t kSubsliceDisableMask = 0xf << kSubsliceDisableShift; |
| |
| static void read(MsdIntelRegisterIo* register_io, uint32_t* slice_enable_mask_out, |
| uint32_t* subslice_enable_mask_out) { |
| uint32_t val = register_io->Read32(kOffset); |
| *slice_enable_mask_out = (val & kSliceEnableMask) >> kSliceEnableShift; |
| *subslice_enable_mask_out = ((~val) & kSubsliceDisableMask) >> kSubsliceDisableShift; |
| } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.398 |
| class MirrorEuDisable { |
| public: |
| static constexpr uint32_t kOffset = 0x9134; |
| |
| static constexpr uint32_t kMaxSliceCount = 3; |
| static constexpr uint32_t kMaxSubsliceCount = 4; |
| static constexpr uint32_t kEuPerSubslice = 8; |
| static constexpr uint32_t kSubsliceMask = 0xff; |
| |
| static_assert(kMaxSubsliceCount * kEuPerSubslice == sizeof(uint32_t) * 8, |
| "eu/subslice math is wrong"); |
| static_assert(kSubsliceMask == (1 << kEuPerSubslice) - 1, "wrong kSubsliceMask"); |
| |
| static void read(MsdIntelRegisterIo* register_io, uint8_t slice, |
| std::vector<uint32_t>& eu_disable_mask_out) { |
| DASSERT(slice < kMaxSliceCount); |
| uint32_t val = register_io->Read32(kOffset + slice * sizeof(uint32_t)); |
| |
| eu_disable_mask_out.clear(); |
| |
| for (uint32_t subslice = 0; subslice < kMaxSubsliceCount; subslice++) { |
| eu_disable_mask_out.push_back(val & kSubsliceMask); |
| val >>= kEuPerSubslice; |
| } |
| } |
| }; |
| |
| // MIRROR_EU_DISABLE0 |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part2-rev2_1.pdf |
| // p.81 |
| class MirrorEuDisableGen12 { |
| public: |
| static constexpr uint32_t kOffset = 0x9134; |
| |
| static constexpr uint32_t kEusPerSubslice = 16; |
| static constexpr uint32_t kEuDisableBits = kEusPerSubslice / 2; |
| static constexpr uint32_t kEuDisableBitMask = (1 << kEuDisableBits) - 1; |
| |
| // EU disable bits are the same for every subslice. |
| static std::bitset<kEuDisableBits> read(MsdIntelRegisterIo* register_io) { |
| uint32_t val = register_io->Read32(kOffset); |
| |
| return std::bitset<kEuDisableBits>(val & kEuDisableBitMask); |
| } |
| }; |
| |
| // GEN12_GT_GEOMETRY_DSS_ENABLE |
| // https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02c-commandreference-registers-part2-rev2_1.pdf |
| // p.97 |
| class MirrorDssEnable { |
| public: |
| static constexpr uint32_t kOffset = 0x913C; |
| |
| static constexpr uint32_t kDssPerSlice = 6; |
| static constexpr uint32_t kDssEnableMask = (1 << kDssPerSlice) - 1; |
| static constexpr uint32_t kMaxSlice = 32 / kDssPerSlice; |
| |
| // Reads the dual-subslice enable masks. |
| static std::vector<std::bitset<kDssPerSlice>> read(MsdIntelRegisterIo* register_io) { |
| uint32_t val = register_io->Read32(kOffset); |
| |
| std::vector<std::bitset<kDssPerSlice>> dss_enable_masks; |
| |
| for (uint32_t i = 0; i < kMaxSlice; i++) { |
| dss_enable_masks.push_back((val >> (i * kDssPerSlice)) & kDssEnableMask); |
| } |
| |
| return dss_enable_masks; |
| } |
| }; |
| |
| // PWR_WELL_CTL: Power well control. This allows enabling or disabling |
| // power to various "power wells" (groups of functional units). |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf |
| class PowerWellControl2 : public hwreg::RegisterBase<PowerWellControl2, uint32_t> { |
| public: |
| DEF_BIT(31, power_well_2_request); |
| DEF_BIT(30, power_well_2_state); |
| DEF_BIT(29, power_well_1_request); |
| DEF_BIT(28, power_well_1_state); |
| DEF_BIT(9, ddi_d_io_power_request); |
| DEF_BIT(8, ddi_d_io_power_state); |
| DEF_BIT(7, ddi_c_io_power_request); |
| DEF_BIT(6, ddi_c_io_power_state); |
| DEF_BIT(5, ddi_b_io_power_request); |
| DEF_BIT(4, ddi_b_io_power_state); |
| DEF_BIT(3, ddi_a_and_e_io_power_request); |
| DEF_BIT(2, ddi_a_and_e_io_power_state); |
| DEF_BIT(1, misc_io_power_request); |
| DEF_BIT(0, misc_io_power_state); |
| |
| static auto Get() { return hwreg::RegisterAddr<PowerWellControl2>(0x45404); } |
| }; |
| |
| // from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.86 |
| class ArbiterControl { |
| public: |
| static constexpr uint32_t kOffset = 0xb004; |
| static constexpr uint32_t kGapsTsvCreditFixEnable = 1 << 7; |
| |
| static void workaround(MsdIntelRegisterIo* register_io) { |
| uint32_t value = register_io->Read32(kOffset) | kGapsTsvCreditFixEnable; |
| register_io->Write32(value, kOffset); |
| } |
| }; |
| |
| class RenderEngineTlbControl : public hwreg::RegisterBase<RenderEngineTlbControl, uint32_t> { |
| public: |
| DEF_BIT(0, invalidate); |
| static auto Get() { return hwreg::RegisterAddr<RenderEngineTlbControl>(0x4260); } |
| }; |
| |
| class VideoEngineTlbControl : public hwreg::RegisterBase<VideoEngineTlbControl, uint32_t> { |
| public: |
| DEF_BIT(0, invalidate); |
| static auto Get() { return hwreg::RegisterAddr<VideoEngineTlbControl>(0x4264); } |
| }; |
| |
| class CacheMode1 { |
| public: |
| static constexpr uint32_t kOffset = 0x7004; |
| static constexpr uint32_t k4x4StcOptimizationDisable = 1 << 6; |
| static constexpr uint32_t kPartialResolveInVcDisable = 1 << 1; |
| }; |
| |
| class RegisterOffset7300 { |
| public: |
| static constexpr uint32_t kOffset = 0x7300; |
| static constexpr uint16_t kWaForceEnableNonCoherent = 1 << 4; |
| }; |
| |
| } // namespace registers |
| |
| #endif // REGISTERS_H |