genode/repos/os/src/drivers/gpu/intel/context.h
Josef Söntgen 198019edca os: add Gpu driver for Intel Gen8 HD graphics
This commit introduces a experimental 3D driver for Intel Gen8 HD
graphics devices as well as the corresponding Gpu session.

Fixes #2507.
2017-08-30 09:59:57 +02:00

886 lines
23 KiB
C++

/*
* \brief Broadwell logical ring context
* \author Josef Soentgen
* \date 2017-03-15
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _LOGICAL_RING_CONTEXT_H_
#define _LOGICAL_RING_CONTEXT_H_
/* Genode includes */
#include <util/mmio.h>
#include <util/string.h>
/* local includes */
#include <types.h>
#include <commands.h>
namespace Igd {
struct Context_status_qword;
struct Common_context_regs;
struct Hardware_status_page;
template <addr_t RING_BASE> class Execlist_context;
template <addr_t RING_BASE> class Ppgtt_context;
class Engine_context;
class Ext_engine_context;
class Urb_atomic_context;
class Rcs_context;
}
/*
* IHD-OS-BDW-Vol 6-11.15 p. 8
* IHD-OS-BDW-Vol 2d-11.15 p. 111
*/
struct Igd::Context_status_qword : Genode::Register<64>
{
struct Context_id : Bitfield<32, 32> { };
/* only valid if Preempted set bit */
struct Lite_restore : Bitfield<15, 1> { };
struct Display_plane : Bitfield<12, 3>
{
enum {
DISPLAY_PLANE_A = 0b000,
DISPLAY_PLANE_B = 0b001,
DISPLAY_PLANE_C = 0b010,
DISPLAY_PLANE_SPRITE_A = 0b011,
DISPLAY_PLANE_SPRITE_B = 0b100,
DISPLAY_PLANE_SPRITE_C = 0b101,
};
};
/* only valid if Wait_on_semaphore bit set */
struct Semaphore_wait_mode : Bitfield<11, 1>
{
enum {
SIGNAL_MODE = 0b00,
POLL_MODE = 0b01,
};
};
struct Wait_on_scanline : Bitfield< 8, 1> { };
struct Wait_on_semaphore : Bitfield< 7, 1> { };
struct Wait_on_v_blank : Bitfield< 6, 1> { };
struct Wait_on_sync_flip : Bitfield< 5, 1> { };
struct Context_complete : Bitfield< 4, 1> { };
struct Active_to_idle : Bitfield< 3, 1> { };
struct Element_switch : Bitfield< 2, 1> { };
struct Preempted : Bitfield< 1, 1> { };
struct Idle_to_active : Bitfield< 0, 1> { };
};
struct Igd::Common_context_regs : public Genode::Mmio
{
template <long int OFFSET>
struct Common_register : Register<OFFSET * sizeof(uint32_t), 32> { };
template <long int OFFSET, size_t NUM>
struct Common_register_array : Register_array<OFFSET * sizeof(uint32_t), 32, NUM, 32> { };
addr_t _base;
Common_context_regs(addr_t base) : Genode::Mmio(base), _base(base) { }
addr_t base() const { return _base; }
template <typename T>
void write_offset(typename T::access_t const value)
{
write<T>(value + T::OFFSET);
}
};
/*
* IHD-OS-BDW-Vol 3-11.15 p. 18 (for VCS)
* IHD-OS-BDW-Vol 3-11.15 p. 20 (for BCS)
* IHD-OS-BDW-Vol 3-11.15 p. 22 (for VECS)
* IHD-OS-BDW-Vol 7-11.15 p. 27 (for RCS)
*
* All engines use the same layout until offset 0x118.
*/
template <Genode::addr_t RING_BASE>
class Igd::Execlist_context : public Igd::Common_context_regs
{
public:
/* MI_NOOP */
struct Noop_1 : Common_register<0x0000> { };
/*
* IHD-OS-BDW-Vol 2a-11.15 p. 841 ff.
*/
struct Load_immediate_header : Common_register<0x0001> { };
/*
* XXX see i915 intel_lrc.h
*/
struct Context_control_mmio : Common_register<0x0002>
{
enum { OFFSET = 0x244, };
};
struct Context_control_value : Common_register<0x0003>
{
using R = Common_register<0x0003>;
struct Mask_bits : R::template Bitfield<16, 16> { };
struct Inhibit_syn_context_switch_mask : R::template Bitfield<18, 1> { };
struct Inhibit_syn_context_switch : R::template Bitfield< 3, 1> { };
struct Rs_context_enable_mask : R::template Bitfield<17, 1> { };
struct Rs_context_enable : R::template Bitfield< 1, 1> { };
struct Engine_context_restore_inhibit_mask : R::template Bitfield<16, 1> { };
struct Engine_context_restore_inhibit : R::template Bitfield< 0, 1> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1350 ff
*/
struct Ring_buffer_head_mmio : Common_register<0x0004>
{
enum { OFFSET = 0x34, };
};
struct Ring_buffer_head_value : Common_register<0x0005>
{
using R = Common_register<0x0005>;
struct Wrap_count : R::template Bitfield<21,11> { };
struct Head_offset : R::template Bitfield< 2,19> { };
struct Reserved_mbz : R::template Bitfield< 0, 2> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1353 ff
*/
struct Ring_buffer_tail_mmio : Common_register<0x0006>
{
enum { OFFSET = 0x30, };
};
struct Ring_buffer_tail_value : Common_register<0x0007>
{
using R = Common_register<0x0007>;
struct Reserved_mbz_1 : R::template Bitfield<21, 11> { };
struct Tail_offset : R::template Bitfield< 3, 18> { };
struct Reserved_mbz_2 : R::template Bitfield< 0, 3> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1352 ff
*/
struct Ring_buffer_start_mmio : Common_register<0x0008>
{
enum { OFFSET = 0x38, };
};
struct Ring_buffer_start_value : Common_register<0x0009>
{
using R = Common_register<0x0009>;
struct Starting_address : R::template Bitfield<12, 20> { };
struct Reserved_mbz : R::template Bitfield< 0, 12> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1345 ff
*/
struct Ring_buffer_control_mmio : Common_register<0x000A>
{
enum { OFFSET = 0x3c, };
};
struct Ring_buffer_control_value : Common_register<0x000B>
{
using R = Common_register<0x000B>;
struct Reserved_mbz_1 : R::template Bitfield<21, 11> { };
struct Buffer_length : R::template Bitfield<12, 9> { };
struct RBwait : R::template Bitfield<11, 1>
{
enum { CLEAR = 0b01, };
};
struct Semaphore_wait : R::template Bitfield<10, 1>
{
enum { CLEAR = 0b01, };
};
struct Reserved_mbz_2 : R::template Bitfield< 3, 7> { };
struct Arhp : R::template Bitfield< 1, 2>
{
enum {
MI_AUTOREPORT_OFF = 0,
MI_AUTOREPORT_64KB = 1,
MI_AUTOREPORT_4KB = 2,
MI_AUTOREPORT_128KB = 3
};
};
struct Ring_buffer_enable : R::template Bitfield< 0, 1> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 142
*/
struct Bb_addr_udw_mmio : Common_register<0x000C>
{
enum { OFFSET = 0x168, };
};
struct Bb_addr_udw_value : Common_register<0x000D> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 129
*/
struct Bb_addr_mmio : Common_register<0x000E>
{
enum { OFFSET = 0x140, };
};
struct Bb_addr_value : Common_register<0x000F> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 138
*/
struct Bb_state_mmio : Common_register<0x0010>
{
enum { OFFSET = 0x110, };
};
struct Bb_state_value : Common_register<0x0011>
{
struct Address_space_indicator : Bitfield<5, 1> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1402
*/
struct Sbb_addr_udw_mmio : Common_register<0x0012>
{
enum { OFFSET = 0x11C, };
};
struct Sbb_addr_udw_value : Common_register<0x0013> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1397
*/
struct Sbb_addr_mmio : Common_register<0x0014>
{
enum { OFFSET = 0x114, };
};
struct Sbb_addr_value : Common_register<0x0015> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1399
*/
struct Sbb_state_mmio : Common_register<0x0016>
{
enum { OFFSET = 0x118, };
};
struct Sbb_state_value : Common_register<0x0017> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 131 ff
*
* RCS only
*/
struct Bb_per_ctx_ptr_mmio : Common_register<0x0018>
{
enum { OFFSET = 0x1C0, };
};
struct Bb_per_ctx_ptr_value : Common_register<0x0019>
{
using R = Common_register<0x0019>;
struct Address : R::template Bitfield<12, 20> { };
struct Reserved_mbz : R::template Bitfield< 2, 10> { };
struct Enable : R::template Bitfield< 1, 1> { };
struct Valid : R::template Bitfield< 0, 1> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 821 ff
*
* RCS only
*/
struct Rcs_indirect_ctx_mmio : Common_register<0x001A>
{
enum { OFFSET = 0x1C4, };
};
struct Rcs_indirect_ctx_value : Common_register<0x001B>
{
using R = Common_register<0x001B>;
struct Address : R::template Bitfield< 6, 26> { };
struct Size : R::template Bitfield< 0, 6> { };
};
/*
* XXX
*
* RCS only
*/
struct Rcs_indirect_ctx_offset_mmio : Common_register<0x001C>
{
enum { OFFSET = 0x1C8, };
};
struct Rcs_indirect_ctx_offset_value : Common_register<0x001D>
{
using R = Common_register<0x001D>;
struct Reserved_mbz_1 : R::template Bitfield<16, 16> { };
struct Offset : R::template Bitfield< 6, 10> { };
struct Reserved_mbz_2 : R::template Bitfield< 0, 6> { };
};
/*
* XXX
*
* RCS only
*/
struct Rcs_noop_1 : Common_register_array<0x001E, 2> { };
public:
Execlist_context(addr_t base,
addr_t ring_buffer_start,
size_t ring_buffer_length,
uint32_t immediate_header)
:
Common_context_regs(base)
{
write<Load_immediate_header>(immediate_header);
write_offset<Context_control_mmio>(RING_BASE);
{
typename Context_control_value::access_t v = read<Context_control_value>();
Context_control_value::Engine_context_restore_inhibit_mask::set(v, 1);
Context_control_value::Engine_context_restore_inhibit::set(v, 1);
Context_control_value::Inhibit_syn_context_switch_mask::set(v, 1);
Context_control_value::Inhibit_syn_context_switch::set(v, 1);
write<Context_control_value>(v);
}
write_offset<Ring_buffer_head_mmio>(RING_BASE);
write_offset<Ring_buffer_tail_mmio>(RING_BASE);
write_offset<Ring_buffer_start_mmio>(RING_BASE);
{
typename Ring_buffer_start_value::access_t v = read<Ring_buffer_start_value>();
/* shift ring_buffer_start value accordingly */
typename Ring_buffer_start_value::access_t const addr = Ring_buffer_start_value::Starting_address::get(ring_buffer_start);
Ring_buffer_start_value::Starting_address::set(v, addr);
write<Ring_buffer_start_value>(v);
}
write_offset<Ring_buffer_control_mmio>(RING_BASE);
{
typename Ring_buffer_control_value::access_t v = read<Ring_buffer_control_value>();
/* length is given in number of pages */
Ring_buffer_control_value::Buffer_length::set(v, ring_buffer_length / PAGE_SIZE);
/* according to the PRM it should be disable b/c of the amount of reports generated */
Ring_buffer_control_value::Arhp::set(v, Ring_buffer_control_value::Arhp::MI_AUTOREPORT_OFF);
Ring_buffer_control_value::Ring_buffer_enable::set(v, 1);
write<Ring_buffer_control_value>(v);
}
write_offset<Bb_addr_udw_mmio>(RING_BASE);
write_offset<Bb_addr_mmio>(RING_BASE);
write_offset<Bb_state_mmio>(RING_BASE);
{
/* should actually not be written by software */
typename Bb_state_value::access_t v = 0;
Bb_state_value::Address_space_indicator::set(v, 1);
write<Bb_state_value>(v);
}
write_offset<Sbb_addr_udw_mmio>(RING_BASE);
write_offset<Sbb_addr_mmio>(RING_BASE);
write_offset<Sbb_state_mmio>(RING_BASE);
}
size_t tail_offset()
{
return read<typename Ring_buffer_tail_value::Tail_offset>();
}
void tail_offset(size_t offset)
{
write<typename Ring_buffer_tail_value::Tail_offset>(offset);
}
size_t head_offset()
{
return read<typename Ring_buffer_head_value::Head_offset>();
}
/*********************
** Debug interface **
*********************/
void dump()
{
using namespace Genode;
log("Execlist_context");
log(" Load_immediate_header: ", Hex(read<Load_immediate_header>(), Hex::PREFIX, Hex::PAD));
log(" Context_control: ", Hex(read<Context_control_value>(), Hex::PREFIX, Hex::PAD));
log(" Ring_buffer_head: ", Hex(read<Ring_buffer_head_value>(), Hex::PREFIX, Hex::PAD));
log(" Wrap_count: ", Hex(read<typename Ring_buffer_head_value::Wrap_count>(), Hex::PREFIX, Hex::PAD));
log(" Ring_buffer_tail: ", Hex(read<Ring_buffer_tail_value>(), Hex::PREFIX, Hex::PAD));
log(" Ring_buffer_start: ", Hex(read<Ring_buffer_start_value>(), Hex::PREFIX, Hex::PAD));
log(" Ring_buffer_control: ", Hex(read<Ring_buffer_control_value>(), Hex::PREFIX, Hex::PAD));
log(" Bb_addr_udw: ", Hex(read<Bb_addr_udw_value>(), Hex::PREFIX, Hex::PAD));
log(" Bb_addr: ", Hex(read<Bb_addr_value>(), Hex::PREFIX, Hex::PAD));
log(" Bb_state: ", Hex(read<Bb_state_value>(), Hex::PREFIX, Hex::PAD));
log(" Sbb_addr_udw: ", Hex(read<Sbb_addr_udw_value>(), Hex::PREFIX, Hex::PAD));
log(" Sbb_addr: ", Hex(read<Sbb_addr_value>(), Hex::PREFIX, Hex::PAD));
log(" Sbb_state: ", Hex(read<Sbb_state_value>(), Hex::PREFIX, Hex::PAD));
}
};
template <Genode::addr_t RING_BASE>
class Igd::Ppgtt_context : public Igd::Common_context_regs
{
public:
/* MI_NOOP */
struct Noop_1 : Common_register<0x0020> { };
/*
* IHD-OS-BDW-Vol 2a-11.15 p. 841 ff.
*/
struct Load_immediate_header : Common_register<0x0021> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 283
*
* RCS only
*/
struct Cs_ctx_timestamp_mmio : Common_register<0x0022>
{
enum { OFFSET = 0x3A8, };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1143
*/
struct Pdp_3_udw_mmio : Common_register<0x0024>
{
enum { OFFSET = 0x28C, };
};
struct Pdp_3_udw_value : Common_register<0x0025>
{
struct Value : Bitfield<0,32> { };
};
struct Pdp_3_ldw_mmio : Common_register<0x0026>
{
enum { OFFSET = 0x288, };
};
struct Pdp_3_ldw_value : Common_register<0x0027>
{
struct Value : Bitfield<0,32> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1142
*/
struct Pdp_2_udw_mmio : Common_register<0x0028>
{
enum { OFFSET = 0x284, };
};
struct Pdp_2_udw_value : Common_register<0x0029>
{
struct Value : Bitfield<0,32> { };
};
struct Pdp_2_ldw_mmio : Common_register<0x002A>
{
enum { OFFSET = 0x280, };
};
struct Pdp_2_ldw_value : Common_register<0x002B>
{
struct Value : Bitfield<0,32> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1141
*/
struct Pdp_1_udw_mmio : Common_register<0x002C>
{
enum { OFFSET = 0x27C, };
};
struct Pdp_1_udw_value : Common_register<0x002D>
{
struct Value : Bitfield<0,32> { };
};
struct Pdp_1_ldw_mmio : Common_register<0x002E>
{
enum { OFFSET = 0x278, };
};
struct Pdp_1_ldw_value : Common_register<0x002F>
{
struct Value : Bitfield<0,32> { };
};
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1140
*/
struct Pdp_0_udw_mmio : Common_register<0x0030>
{
enum { OFFSET = 0x274, };
};
struct Pdp_0_udw_value : Common_register<0x0031>
{
struct Value : Bitfield<0,32> { };
};
struct Pdp_0_ldw_mmio : Common_register<0x0032>
{
enum { OFFSET = 0x270, };
};
struct Pdp_0_ldw_value : Common_register<0x0033>
{
struct Value : Bitfield<0,32> { };
};
struct Noop_2 : Common_register_array<0x0034, 12> { };
struct Noop_3 : Common_register_array<0x0040, 1> { };
struct Load_immediate_header_2 : Common_register<0x0041> { };
/*
* IHD-OS-BDW-Vol 2c-11.15 p. 1325
*/
struct R_pwr_clk_state_mmio : Common_register<0x0042>
{
enum { OFFSET = 0x0C8, };
};
struct R_pwr_clk_state_value : Common_register<0x0043>
{
using R = Common_register<0x0043>;
struct Power_clock_state_enable : R::template Bitfield<31, 1> { };
struct Power_clock_state : R::template Bitfield< 0, 31> { };
};
/*
* IHD-OS-BDW-Vol 7-11.15 p. 659
*/
struct Gpgpu_csr_base_Address : Common_register_array<0x00044, 3> { };
struct Noop_4 : Common_register_array<0x0047, 9> { };
public:
Ppgtt_context(addr_t base, uint64_t plm4_addr)
:
Common_context_regs(base)
{
write<Load_immediate_header>(0x11001011);
write_offset<Cs_ctx_timestamp_mmio>(RING_BASE);
{
write<Cs_ctx_timestamp_mmio>(0);
}
write_offset<Pdp_3_udw_mmio>(RING_BASE);
write_offset<Pdp_3_ldw_mmio>(RING_BASE);
write_offset<Pdp_2_udw_mmio>(RING_BASE);
write_offset<Pdp_2_ldw_mmio>(RING_BASE);
write_offset<Pdp_1_udw_mmio>(RING_BASE);
write_offset<Pdp_1_ldw_mmio>(RING_BASE);
write_offset<Pdp_0_udw_mmio>(RING_BASE);
{
Genode::uint32_t const udw = (Genode::uint32_t)((plm4_addr >> 16) >> 16);
write<Pdp_0_udw_value>(udw);
}
write_offset<Pdp_0_ldw_mmio>(RING_BASE);
{
Genode::uint32_t const ldw = (Genode::uint32_t)plm4_addr;
write<Pdp_0_ldw_value>(ldw);
}
write_offset<R_pwr_clk_state_mmio>(RING_BASE);
}
/*********************
** Debug interface **
*********************/
void dump()
{
using namespace Genode;
using C = Ppgtt_context<RING_BASE>;
log("Ppgtt_context");
log(" Pdp_0_udw: ", Hex(read<C::Pdp_0_udw_value>(), Hex::PREFIX, Hex::PAD));
log(" Pdp_0_ldw: ", Hex(read<C::Pdp_0_ldw_value>(), Hex::PREFIX, Hex::PAD));
}
};
/*
* TODO
*/
class Igd::Engine_context
{
public:
Engine_context() { }
};
/*
* TODO
*/
class Igd::Ext_engine_context
{
public:
Ext_engine_context() { }
};
/*
* TODO
*/
class Igd::Urb_atomic_context
{
public:
Urb_atomic_context() { }
};
/*
* IHD-OS-BDW-Vol 2d-11.15 p. 199
*/
class Igd::Hardware_status_page : public Igd::Common_context_regs
{
public:
/*
* See ISR register definition
*/
struct Interrupt_status_register_storage : Common_register<0> { };
/*
* See RING_BUFFER_HEAD_RCSUNIT definition
*/
struct Ring_head_ptr_storage : Common_register<4> { };
/*
* See CTXT_ST_BUF
*/
enum { CONTEXT_STATUS_DWORDS_NUM = 12, };
struct Context_status_dwords : Common_register_array<16, CONTEXT_STATUS_DWORDS_NUM> { };
struct Last_written_status_offset : Common_register<31> { };
Hardware_status_page(addr_t base)
: Common_context_regs(base) { }
};
/*
*/
class Igd::Rcs_context
{
public:
enum {
HW_ID = 0,
CONTEXT_PAGES = 20 /* ctx */ + 1 /* GuC */,
RING_PAGES = 4,
RCS_RING_BASE = 0x2000,
HW_STATUS_PAGE_SIZE = PAGE_SIZE,
/*
* IHD-OS-BDW-Vol 7-11.15 p. 27 ff
*/
EXECLIST_CTX_START = 0x0000,
EXECLIST_CTX_END = 0x0020,
EXECLIST_CTX_SIZE = (EXECLIST_CTX_END - EXECLIST_CTX_START) * sizeof(uint32_t),
EXECLIST_CTX_IH = 0x1100101B,
PPGTT_CTX_START = EXECLIST_CTX_END,
PPGTT_CTX_END = 0x0050,
PPGTT_CTX_SIZE = (PPGTT_CTX_END - PPGTT_CTX_START) * sizeof(uint32_t),
PPGTT_CTX_IH = 0x11000001,
ENGINE_CTX_START = PPGTT_CTX_END,
ENGINE_CTX_END = 0x0EC0,
ENGINE_CTX_SIZE = (ENGINE_CTX_END - ENGINE_CTX_START) * sizeof(uint32_t),
EXT_ENGINE_CTX_START = ENGINE_CTX_END,
EXT_ENGINE_CTX_END = 0x26B0,
URB_ATOMIC_STORE_START = EXT_ENGINE_CTX_END,
URB_ATOMIC_STORE_END = 0x46B0,
URB_ATOMIC_STORE_SIZE = (URB_ATOMIC_STORE_END - URB_ATOMIC_STORE_START) * sizeof(uint32_t),
};
private:
Hardware_status_page _hw_status_page;
Execlist_context<RCS_RING_BASE> _execlist_context;
Ppgtt_context<RCS_RING_BASE> _ppgtt_context;
Engine_context _engine_context;
Ext_engine_context _ext_engine_context;
Urb_atomic_context _urb_atomic_context;
public:
Rcs_context(addr_t map_base,
addr_t ring_buffer_start,
size_t ring_buffer_length,
uint64_t plm4_addr)
:
_hw_status_page(map_base),
_execlist_context((addr_t)(map_base + HW_STATUS_PAGE_SIZE),
ring_buffer_start, ring_buffer_length,
EXECLIST_CTX_IH),
_ppgtt_context((addr_t)(map_base + HW_STATUS_PAGE_SIZE), plm4_addr),
_engine_context(),
_ext_engine_context(),
_urb_atomic_context()
{
Genode::log(__func__, ":",
" map_base:", Genode::Hex(map_base),
" ring_buffer_start:", Genode::Hex(ring_buffer_start),
" ring_buffer_length:", Genode::Hex(ring_buffer_length),
" plm4_addr:", Genode::Hex(plm4_addr, Genode::Hex::PREFIX, Genode::Hex::PAD));
using C = Execlist_context<RCS_RING_BASE>;
_execlist_context.write_offset<C::Bb_per_ctx_ptr_mmio>(RCS_RING_BASE);
{
using R = C::Bb_per_ctx_ptr_value;
typename R::access_t v = _execlist_context.read<R>();
R::Address::set(v, 0);
R::Valid::set(v, 0);
_execlist_context.write<R>(v);
}
_execlist_context.write_offset<C::Rcs_indirect_ctx_mmio>(RCS_RING_BASE);
{
using R = C::Rcs_indirect_ctx_value;
typename R::access_t v = _execlist_context.read<R>();
R::Address::set(v, 0);
R::Size::set(v, 0);
_execlist_context.write<R>(v);
}
_execlist_context.write_offset<C::Rcs_indirect_ctx_offset_mmio>(RCS_RING_BASE);
{
using R = C::Rcs_indirect_ctx_offset_value;
typename R::access_t v = _execlist_context.read<R>();
R::Offset::set(v, 0);
_execlist_context.write<R>(v);
}
using P = Ppgtt_context<RCS_RING_BASE>;
_ppgtt_context.write<P::Load_immediate_header_2>(PPGTT_CTX_IH);
}
size_t head_offset()
{
return _execlist_context.head_offset();
}
void tail_offset(addr_t offset)
{
_execlist_context.tail_offset(offset);
}
/*********************
** Debug interface **
*********************/
void dump()
{
using namespace Genode;
log("Rcs_context");
log(" HW status page: ", Hex(_hw_status_page.base(), Hex::PREFIX, Hex::PAD));
log(" Execlist_context: ", Hex(_execlist_context.base(), Hex::PREFIX, Hex::PAD));
log(" Ppgtt_context: ", Hex(_ppgtt_context.base(), Hex::PREFIX, Hex::PAD));
_execlist_context.dump();
using C = Execlist_context<RCS_RING_BASE>;
log(" Bb_per_ctx_ptr: ", Hex(_execlist_context.read<C::Bb_per_ctx_ptr_value>(), Hex::PREFIX, Hex::PAD));
log(" Rcs_indirect_ctx: ", Hex(_execlist_context.read<C::Rcs_indirect_ctx_value>(), Hex::PREFIX, Hex::PAD));
log(" Rcs_indirect_ctx_offset: ", Hex(_execlist_context.read<C::Rcs_indirect_ctx_offset_value>(), Hex::PREFIX, Hex::PAD));
_ppgtt_context.dump();
}
void dump_hw_status_page(bool raw = false)
{
using namespace Genode;
if (raw) {
uint32_t const *p = (uint32_t const *)_hw_status_page.base();
for (uint32_t i = 0; i < HW_STATUS_PAGE_SIZE / sizeof(uint32_t); i += 8) {
log(Hex(i, Hex::PREFIX, Hex::PAD), " ",
Hex(p[i ], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+1], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+2], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+3], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+4], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+5], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+6], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+7], Hex::PREFIX, Hex::PAD));
}
} else {
using H = Hardware_status_page;
log("Hardware_status_page");
log(" Interrupt_status_register_storage: ",
Hex(_hw_status_page.read<H::Interrupt_status_register_storage>(),
Hex::PREFIX, Hex::PAD));
log(" Ring_head_ptr_storage: ",
Hex(_hw_status_page.read<H::Ring_head_ptr_storage>(),
Hex::PREFIX, Hex::PAD));
for (int i = 0; i < H::CONTEXT_STATUS_DWORDS_NUM; i++) {
log(" Context_status_dwords: ",
Hex(_hw_status_page.read<H::Context_status_dwords>(i),
Hex::PREFIX, Hex::PAD));
}
log(" Last_written_status_offset: ",
Hex(_hw_status_page.read<H::Last_written_status_offset>(),
Hex::PREFIX, Hex::PAD));
}
}
void dump_execlist_context()
{
using namespace Genode;
log("Execlist_context");
uint32_t const *p = (uint32_t const *)_execlist_context.base();
for (uint32_t i = 0; i < EXECLIST_CTX_SIZE / sizeof(uint32_t); i += 8) {
log(" ", Hex(i, Hex::PREFIX, Hex::PAD), " ",
Hex(p[i ], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+1], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+2], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+3], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+4], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+5], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+6], Hex::PREFIX, Hex::PAD), " ",
Hex(p[i+7], Hex::PREFIX, Hex::PAD));
}
}
};
#endif /* _LOGICAL_RING_CONTEXT_H_ */