blob: 6ef9a4c7b743783d76e7dea87295abd54866591f [file] [log] [blame]
// 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