blob: 324d5d126c01a326fcb6fbe0cd4312be78919b67 [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 HARDWARE_STATUS_PAGE_H
#define HARDWARE_STATUS_PAGE_H
#include <lib/magma/util/short_macros.h>
#include <optional>
#include "address_space.h"
#include "gpu_mapping.h"
#include "types.h"
// There is a global HWSP for each engine command streamer, and a per-process
// HWSP for each context. The layout of GHWSP and PPHWSP differs.
class GlobalHardwareStatusPage {
public:
GlobalHardwareStatusPage(EngineCommandStreamerId id, std::unique_ptr<GpuMapping> mapping)
: id_(id), mapping_(std::move(mapping)) {
if (!mapping_->buffer()->platform_buffer()->MapCpu(&cpu_addr_)) {
DASSERT(false);
cpu_addr_ = 0;
}
}
EngineCommandStreamerId id() { return id_; }
uint64_t gpu_addr() { return mapping_->gpu_addr(); }
void write_sequence_number(uint32_t val) {
write_general_purpose_offset(val, kSequenceNumberOffset);
}
uint32_t read_sequence_number() { return read_general_purpose_offset(kSequenceNumberOffset); }
void InitContextStatusGen12();
// Reads all available context status entries; if there are any, then |idle_out| is set
// according to the most recent status. Updates |read_index|.
void ReadContextStatus(uint64_t& read_index, std::optional<bool>* idle_out);
void ReadContextStatusGen12(uint64_t& read_index, std::optional<bool>* idle_out);
// from intel-gfx-prm-osrc-kbl-vol02d-commandreference-structures.pdf pp.284-286
// https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol02d-commandreference-structures_0.pdf
// p.600
static constexpr uint32_t kContextStatusStartOffset = 16 * sizeof(uint32_t);
static constexpr uint32_t kContextStatusEndOffsetGen12 = 39 * sizeof(uint32_t);
static constexpr uint32_t kLastWrittenContextStatusOffsetGen12 = 47 * sizeof(uint32_t);
static constexpr uint32_t kGeneralPurposeStartOffset = 48 * sizeof(uint32_t);
static constexpr uint32_t kGeneralPurposeEndOffset = 1023 * sizeof(uint32_t);
static constexpr uint64_t kStatusQwordsGen12 = 12;
static_assert(kStatusQwordsGen12 * sizeof(uint64_t) ==
kContextStatusEndOffsetGen12 - kContextStatusStartOffset + sizeof(uint32_t));
// Our definitions
static constexpr uint32_t kSequenceNumberOffset = kGeneralPurposeStartOffset;
static constexpr uint32_t kScratchOffset = kSequenceNumberOffset + sizeof(uint64_t);
private:
void write_general_purpose_offset(uint32_t val, uint32_t offset) {
DASSERT((offset & 0x3) == 0);
DASSERT(offset >= kGeneralPurposeStartOffset && offset <= kGeneralPurposeEndOffset);
reinterpret_cast<uint32_t*>(cpu_addr_)[offset >> 2] = val;
}
uint32_t read_general_purpose_offset(uint32_t offset) {
DASSERT((offset & 0x3) == 0);
DASSERT(offset >= kGeneralPurposeStartOffset && offset <= kGeneralPurposeEndOffset);
return reinterpret_cast<uint32_t*>(cpu_addr_)[offset >> 2];
}
void write_context_status_gen12(uint32_t offset, std::pair<uint32_t, uint32_t> val) {
DASSERT((offset & 0x3) == 0);
DASSERT(offset >= kContextStatusStartOffset && offset <= kContextStatusEndOffsetGen12);
auto ptr = reinterpret_cast<volatile uint32_t*>(cpu_addr_);
uint32_t index = offset >> 2;
ptr[index] = val.first;
ptr[index + 1] = val.second;
}
std::pair<uint32_t, uint32_t> read_context_status_gen12(uint32_t offset) {
DASSERT((offset & 0x3) == 0);
DASSERT(offset >= kContextStatusStartOffset && offset <= kContextStatusEndOffsetGen12);
auto ptr = reinterpret_cast<volatile uint32_t*>(cpu_addr_);
uint32_t index = offset >> 2;
return {ptr[index], ptr[index + 1]};
}
EngineCommandStreamerId id_;
std::unique_ptr<GpuMapping> mapping_;
void* cpu_addr_;
};
#endif // HARDWARE_STATUS_PAGE_H