mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
gpu/intel: Add support for Gen9+
This commit contains features and buf fixes: * Catch errors during resource allocation * Because Mesa tries to allocate fence (hardware) registers for each batch buffer execution, do not allocate new fences for buffer objects that are already fenced * Add support for global hardware status page. Each context additionally has a per-process hardware status page, which we used to set the global hardware status page during Vgpu switch. This was obviously wrong. There is only one global hardware status page (set once during initialization) and a distinct per-process page for contexts. * Write the sequence number of the currently executing batch buffer to dword 52 of the per-process hardware status page. We use the pipe line command with QW_WRITE (quad word write), GLOBAL_GTT_IVB disabled (address space is per-process address space), and STORE_DATA_INDEX enabled (write goes to offset of hardware status page). This command used to write to the scratch page. But Linux now uses the first reserved word of the per-process hardware status page. * Add Gen9+ WaEnableGapsTsvCreditFix workaround. This sets the "GAPS TSV Credit fix Enable" bit of the Arbiter control register (GARBCNTLREG) as described by the documentation this bit should be set by the BIOS but is not on most Gen9/9.5 platforms. Not setting this bit leads to random GPU hangs. * Increase the context size from 20 to 22 pages for Gen9. On Gen8 the hardware context is 20 pages (1 hardware status page + 19 ring context register pages). On Gen9 the size of the ring context registers has increased by two pages to 21 pages or 81.3125 KBytes as the IGD documentation states. * The logical ring size in the ring buffer control of the execlist context has to be programmed with number of pages - 1. So 0 is 1 page. We programmed the actual number of pages before, leading to ring buffer execution of NOOPs if page behind our ring buffer was empty or GPU hangs if there was data on the page. issue #4260
This commit is contained in:
parent
59b23bc7e1
commit
3daa94ff2e
@ -25,7 +25,10 @@
|
||||
namespace Igd {
|
||||
|
||||
struct Cmd_header;
|
||||
struct Mi_cmd;
|
||||
struct Mi_noop;
|
||||
struct Mi_arb_check;
|
||||
struct Mi_arb_on_off;
|
||||
struct Mi_user_interrupt;
|
||||
struct Mi_batch_buffer_start;
|
||||
struct Pipe_control;
|
||||
@ -57,11 +60,12 @@ struct Igd::Cmd_header : Genode::Register<32>
|
||||
*/
|
||||
struct Mi_cmd_opcode : Bitfield<23, 6>
|
||||
{
|
||||
enum {
|
||||
enum Opcode {
|
||||
MI_NOOP = 0x00,
|
||||
MI_USER_INTERRUPT = 0x02,
|
||||
MI_WAIT_FOR_EVENT = 0x03,
|
||||
MI_FLUSH = 0x04,
|
||||
MI_ARB_CHECK = 0x05,
|
||||
MI_REPORT_HEAD = 0x07,
|
||||
MI_ARB_ON_OFF = 0x08,
|
||||
MI_BATCH_BUFFER_END = 0x0A,
|
||||
@ -94,33 +98,65 @@ struct Igd::Cmd_header : Genode::Register<32>
|
||||
};
|
||||
|
||||
|
||||
struct Igd::Mi_cmd : Cmd_header
|
||||
{
|
||||
Mi_cmd(Mi_cmd_opcode::Opcode opcode)
|
||||
{
|
||||
Cmd_type::set(value, Cmd_type::MI_COMMAND);
|
||||
Mi_cmd_opcode::set(value, opcode);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2a-11.15 p. 870
|
||||
*/
|
||||
struct Igd::Mi_noop : Cmd_header
|
||||
struct Igd::Mi_noop : Mi_cmd
|
||||
{
|
||||
Mi_noop()
|
||||
{
|
||||
Cmd_header::Cmd_type::set(Cmd_header::value,
|
||||
Cmd_header::Cmd_type::MI_COMMAND);
|
||||
Cmd_header::Mi_cmd_opcode::set(Cmd_header::value,
|
||||
Cmd_header::Mi_cmd_opcode::MI_NOOP);
|
||||
}
|
||||
:
|
||||
Mi_cmd(Mi_cmd_opcode::MI_NOOP)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2a-11.15 p. 948 ff.
|
||||
*/
|
||||
struct Igd::Mi_user_interrupt : Cmd_header
|
||||
struct Igd::Mi_user_interrupt : Mi_cmd
|
||||
{
|
||||
|
||||
Mi_user_interrupt()
|
||||
:
|
||||
Mi_cmd(Mi_cmd_opcode::MI_USER_INTERRUPT)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2a-11.15 p. 777 ff.
|
||||
*/
|
||||
struct Igd::Mi_arb_check : Mi_cmd
|
||||
{
|
||||
Mi_arb_check()
|
||||
:
|
||||
Mi_cmd(Mi_cmd_opcode::MI_ARB_CHECK)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2a-11.15 p. 781 ff.
|
||||
*/
|
||||
struct Igd::Mi_arb_on_off : Mi_cmd
|
||||
{
|
||||
struct Enable : Bitfield<0, 1> { };
|
||||
|
||||
Mi_arb_on_off(bool enable)
|
||||
:
|
||||
Mi_cmd(Mi_cmd_opcode::MI_ARB_ON_OFF)
|
||||
{
|
||||
Cmd_header::Cmd_type::set(Cmd_header::value,
|
||||
Cmd_header::Cmd_type::MI_COMMAND);
|
||||
Cmd_header::Mi_cmd_opcode::set(Cmd_header::value,
|
||||
Cmd_header::Mi_cmd_opcode::MI_USER_INTERRUPT);
|
||||
Enable::set(value, enable ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -128,7 +164,7 @@ struct Igd::Mi_user_interrupt : Cmd_header
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2a-11.15 p. 793 ff.
|
||||
*/
|
||||
struct Igd::Mi_batch_buffer_start : Cmd_header
|
||||
struct Igd::Mi_batch_buffer_start : Mi_cmd
|
||||
{
|
||||
struct Address_space_indicator : Bitfield<8, 1>
|
||||
{
|
||||
@ -138,11 +174,9 @@ struct Igd::Mi_batch_buffer_start : Cmd_header
|
||||
struct Dword_length : Bitfield<0, 8> { };
|
||||
|
||||
Mi_batch_buffer_start()
|
||||
:
|
||||
Mi_cmd(Mi_cmd_opcode::MI_BATCH_BUFFER_START)
|
||||
{
|
||||
Cmd_header::Cmd_type::set(Cmd_header::value,
|
||||
Cmd_header::Cmd_type::MI_COMMAND);
|
||||
Cmd_header::Mi_cmd_opcode::set(Cmd_header::value,
|
||||
Cmd_header::Mi_cmd_opcode::MI_BATCH_BUFFER_START);
|
||||
Address_space_indicator::set(Cmd_header::value, Address_space_indicator::PPGTT);
|
||||
|
||||
Dword_length::set(Cmd_header::value, 1);
|
||||
|
@ -32,6 +32,7 @@ namespace Igd {
|
||||
struct Generation;
|
||||
|
||||
struct Hardware_status_page;
|
||||
class Pphardware_status_page;
|
||||
template <addr_t RING_BASE> class Execlist_context;
|
||||
template <addr_t RING_BASE> class Ppgtt_context;
|
||||
class Engine_context;
|
||||
@ -92,7 +93,7 @@ struct Igd::Common_context_regs : public Genode::Mmio
|
||||
struct Common_register_array : Register_array<OFFSET * sizeof(uint32_t), 32, NUM, 32> { };
|
||||
|
||||
template <long int OFFSET, size_t NUM>
|
||||
struct Common_register_array_64 : Register_array<OFFSET * sizeof(uint32_t), 32, NUM, 64> { };
|
||||
struct Common_register_array_64 : Register_array<OFFSET * sizeof(uint32_t), 64, NUM, 64> { };
|
||||
|
||||
addr_t _base;
|
||||
|
||||
@ -397,7 +398,7 @@ class Igd::Execlist_context : public Igd::Common_context_regs
|
||||
{
|
||||
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);
|
||||
Ring_buffer_control_value::Buffer_length::set(v, (ring_buffer_length / PAGE_SIZE) - 1);
|
||||
/* 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);
|
||||
@ -702,6 +703,72 @@ class Igd::Hardware_status_page : public Igd::Common_context_regs
|
||||
|
||||
Hardware_status_page(addr_t base)
|
||||
: Common_context_regs(base) { }
|
||||
|
||||
void dump(bool raw = false)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (raw) {
|
||||
uint32_t const *p = (uint32_t const *)base();
|
||||
for (uint32_t i = 0; i < 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 {
|
||||
log("Hardware_status_page");
|
||||
log(" Interrupt_status_register_storage: ",
|
||||
Hex(read<Interrupt_status_register_storage>(),
|
||||
Hex::PREFIX, Hex::PAD));
|
||||
log(" Ring_head_ptr_storage: ",
|
||||
Hex(read<Ring_head_ptr_storage>(),
|
||||
Hex::PREFIX, Hex::PAD));
|
||||
|
||||
auto const cs_last = read<Last_written_status_offset>();
|
||||
|
||||
log(" Last_written_status_offset: ",
|
||||
Hex(cs_last, Hex::PREFIX, Hex::PAD));
|
||||
|
||||
for (unsigned i = 0; i < CONTEXT_STATUS_REGISTERS; i++) {
|
||||
using C = Igd::Context_status_qword;
|
||||
C::access_t v = read<Context_status_dwords>(i);
|
||||
log(" Context_status ", i);
|
||||
log(" Context_id: ", C::Context_id::get(v));
|
||||
log(" Lite_restore: ", C::Lite_restore::get(v));
|
||||
log(" Display_plane: ", C::Display_plane::get(v));
|
||||
log(" Semaphore_wait_mode: ", C::Semaphore_wait_mode::get(v));
|
||||
log(" Wait_on_scanline: ", C::Wait_on_scanline::get(v));
|
||||
log(" Wait_on_semaphore: ", C::Wait_on_semaphore::get(v));
|
||||
log(" Wait_on_v_blank: ", C::Wait_on_v_blank::get(v));
|
||||
log(" Wait_on_sync_flip: ", C::Wait_on_sync_flip::get(v));
|
||||
log(" Context_complete: ", C::Context_complete::get(v));
|
||||
log(" Active_to_idle: ", C::Active_to_idle::get(v));
|
||||
log(" Element_switch: ", C::Element_switch::get(v));
|
||||
log(" Preempted: ", C::Preempted::get(v));
|
||||
log(" Idle_to_active: ", C::Idle_to_active::get(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* IHD-OS-BDW-Vol 2d-11.15 p. 303
|
||||
*/
|
||||
class Igd::Pphardware_status_page : public Igd::Common_context_regs
|
||||
{
|
||||
public:
|
||||
|
||||
struct Ring_head_ptr_storage : Common_register<4> { };
|
||||
|
||||
Pphardware_status_page(addr_t base)
|
||||
: Common_context_regs(base) { }
|
||||
};
|
||||
|
||||
|
||||
@ -713,7 +780,7 @@ class Igd::Rcs_context
|
||||
|
||||
enum {
|
||||
HW_ID = 0,
|
||||
CONTEXT_PAGES = 20 /* ctx */ + 1 /* GuC */,
|
||||
CONTEXT_PAGES = 22 /* ctx */ + 1 /* GuC */,
|
||||
RING_PAGES = 4,
|
||||
|
||||
RCS_RING_BASE = 0x2000,
|
||||
@ -731,7 +798,8 @@ class Igd::Rcs_context
|
||||
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,
|
||||
PPGTT_CTX_IH = 0x11001011,
|
||||
PPGTT_CTX_IH_2 = 0x11000001,
|
||||
|
||||
ENGINE_CTX_START = PPGTT_CTX_END,
|
||||
ENGINE_CTX_END = 0x0EC0,
|
||||
@ -748,7 +816,7 @@ class Igd::Rcs_context
|
||||
|
||||
private:
|
||||
|
||||
Hardware_status_page _hw_status_page;
|
||||
Pphardware_status_page _hw_status_page;
|
||||
Execlist_context<RCS_RING_BASE> _execlist_context;
|
||||
Ppgtt_context<RCS_RING_BASE> _ppgtt_context;
|
||||
Engine_context _engine_context;
|
||||
@ -808,7 +876,8 @@ class Igd::Rcs_context
|
||||
|
||||
using P = Ppgtt_context<RCS_RING_BASE>;
|
||||
|
||||
_ppgtt_context.write<P::Load_immediate_header_2>(PPGTT_CTX_IH);
|
||||
_ppgtt_context.write<P::Load_immediate_header>(PPGTT_CTX_IH);
|
||||
_ppgtt_context.write<P::Load_immediate_header_2>(PPGTT_CTX_IH_2);
|
||||
}
|
||||
|
||||
size_t head_offset()
|
||||
@ -850,58 +919,6 @@ class Igd::Rcs_context
|
||||
_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));
|
||||
|
||||
auto const cs_last = _hw_status_page.read<H::Last_written_status_offset>();
|
||||
|
||||
log(" Last_written_status_offset: ",
|
||||
Hex(cs_last, Hex::PREFIX, Hex::PAD));
|
||||
|
||||
for (unsigned i = 0; i < H::CONTEXT_STATUS_REGISTERS; i++) {
|
||||
Igd::Context_status_qword::access_t v = _hw_status_page.read<H::Context_status_dwords>(i);
|
||||
log(" Context_status ", i);
|
||||
log(" Context_id: ", Igd::Context_status_qword::Context_id::get(v));
|
||||
log(" Lite_restore: ", Igd::Context_status_qword::Lite_restore::get(v));
|
||||
log(" Display_plane: ", Igd::Context_status_qword::Display_plane::get(v));
|
||||
log(" Semaphore_wait_mode: ", Igd::Context_status_qword::Semaphore_wait_mode::get(v));
|
||||
log(" Wait_on_scanline: ", Igd::Context_status_qword::Wait_on_scanline::get(v));
|
||||
log(" Wait_on_semaphore: ", Igd::Context_status_qword::Wait_on_semaphore::get(v));
|
||||
log(" Wait_on_v_blank: ", Igd::Context_status_qword::Wait_on_v_blank::get(v));
|
||||
log(" Wait_on_sync_flip: ", Igd::Context_status_qword::Wait_on_sync_flip::get(v));
|
||||
log(" Context_complete: ", Igd::Context_status_qword::Context_complete::get(v));
|
||||
log(" Active_to_idle: ", Igd::Context_status_qword::Active_to_idle::get(v));
|
||||
log(" Element_switch: ", Igd::Context_status_qword::Element_switch::get(v));
|
||||
log(" Preempted: ", Igd::Context_status_qword::Preempted::get(v));
|
||||
log(" Idle_to_active: ", Igd::Context_status_qword::Idle_to_active::get(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_execlist_context()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <resources.h>
|
||||
#include <platform_session.h>
|
||||
#include <ring_buffer.h>
|
||||
#include <workarounds.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
@ -467,9 +468,6 @@ struct Igd::Device
|
||||
|
||||
addr_t hw_status_page() const { return ctx.gmaddr(); }
|
||||
|
||||
uint64_t seqno() const {
|
||||
Utils::clflush((uint32_t*)(ctx.vaddr() + 0xc0));
|
||||
return *(uint32_t*)(ctx.vaddr() + 0xc0); }
|
||||
|
||||
private:
|
||||
|
||||
@ -504,11 +502,15 @@ struct Igd::Device
|
||||
|
||||
uint32_t _vgpu_avail { 0 };
|
||||
|
||||
/* global hardware-status page */
|
||||
Constructible<Ggtt_map_memory> _hw_status_ctx { };
|
||||
Constructible<Hardware_status_page> _hw_status_page { };
|
||||
|
||||
struct Vgpu : Genode::Fifo<Vgpu>::Element
|
||||
{
|
||||
enum {
|
||||
APERTURE_SIZE = 32u << 20,
|
||||
MAX_FENCES = 4,
|
||||
MAX_FENCES = 16,
|
||||
};
|
||||
|
||||
Device &_device;
|
||||
@ -556,11 +558,10 @@ struct Igd::Device
|
||||
void user_complete()
|
||||
{
|
||||
/* remember last completed seqno for info object */
|
||||
_completed_seqno = rcs.seqno();
|
||||
_completed_seqno = _device.seqno();
|
||||
}
|
||||
|
||||
bool setup_ring_buffer(Genode::addr_t const buffer_addr,
|
||||
Genode::addr_t const scratch_addr)
|
||||
bool setup_ring_buffer(Genode::addr_t const buffer_addr)
|
||||
{
|
||||
_current_seqno++;
|
||||
|
||||
@ -632,15 +633,12 @@ struct Igd::Device
|
||||
tmp |= Igd::Pipe_control::QW_WRITE;
|
||||
tmp |= Igd::Pipe_control::STORE_DATA_INDEX;
|
||||
|
||||
/*
|
||||
tmp |= Igd::Pipe_control::GLOBAL_GTT_IVB;
|
||||
tmp |= Igd::Pipe_control::DC_FLUSH_ENABLE;
|
||||
tmp |= Igd::Pipe_control::INDIRECT_STATE_DISABLE;
|
||||
tmp |= Igd::Pipe_control::MEDIA_STATE_CLEAR;
|
||||
*/
|
||||
|
||||
cmd[1] = tmp;
|
||||
cmd[2] = scratch_addr;
|
||||
/*
|
||||
* PP-Hardware status page (base GLOBAL_GTT_IVB is disabled)
|
||||
* offset (dword 52) because STORE_DATA_INDEX is enabled.
|
||||
*/
|
||||
cmd[2] = 0x34 * 4;
|
||||
|
||||
for (size_t i = 0; i < CMD_NUM; i++) {
|
||||
advance += el.ring_append(cmd[i]);
|
||||
@ -659,13 +657,6 @@ struct Igd::Device
|
||||
}
|
||||
}
|
||||
|
||||
#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
|
||||
#define MI_NOOP MI_INSTR(0u, 0)
|
||||
#define MI_ARB_ON_OFF MI_INSTR(0x08u, 0)
|
||||
#define MI_ARB_ENABLE (1u<<0)
|
||||
#define MI_ARB_DISABLE (0u<<0)
|
||||
#define MI_ARB_CHECK MI_INSTR(0x05u, 0)
|
||||
|
||||
/*
|
||||
* gen8_emit_bb_start_noarb, gen8 and render engine
|
||||
*
|
||||
@ -677,7 +668,7 @@ struct Igd::Device
|
||||
Genode::uint32_t cmd[CMD_NUM] = {};
|
||||
Igd::Mi_batch_buffer_start mi;
|
||||
|
||||
cmd[0] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
|
||||
cmd[0] = Mi_arb_on_off(false).value;
|
||||
cmd[1] = mi.value;
|
||||
cmd[2] = buffer_addr & 0xffffffff;
|
||||
cmd[3] = (buffer_addr >> 32) & 0xffff;
|
||||
@ -698,12 +689,12 @@ struct Igd::Device
|
||||
Genode::uint32_t cmd[CMD_NUM] = {};
|
||||
Igd::Mi_batch_buffer_start mi;
|
||||
|
||||
cmd[0] = MI_ARB_ON_OFF | MI_ARB_ENABLE;
|
||||
cmd[0] = Mi_arb_on_off(true).value;
|
||||
cmd[1] = mi.value;
|
||||
cmd[2] = buffer_addr & 0xffffffff;
|
||||
cmd[3] = (buffer_addr >> 32) & 0xffff;
|
||||
cmd[4] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
|
||||
cmd[5] = MI_NOOP;
|
||||
cmd[4] = Mi_arb_on_off(false).value;
|
||||
cmd[5] = Mi_noop().value;
|
||||
|
||||
for (size_t i = 0; i < CMD_NUM; i++) {
|
||||
advance += el.ring_append(cmd[i]);
|
||||
@ -721,7 +712,6 @@ struct Igd::Device
|
||||
tmp |= Igd::Pipe_control::RENDER_TARGET_CACHE_FLUSH;
|
||||
tmp |= Igd::Pipe_control::DEPTH_CACHE_FLUSH;
|
||||
tmp |= Igd::Pipe_control::DC_FLUSH_ENABLE;
|
||||
|
||||
cmd[1] = tmp;
|
||||
|
||||
for (size_t i = 0; i < CMD_NUM; i++) {
|
||||
@ -741,9 +731,10 @@ struct Igd::Device
|
||||
tmp |= Igd::Pipe_control::FLUSH_ENABLE;
|
||||
tmp |= Igd::Pipe_control::GLOBAL_GTT_IVB;
|
||||
tmp |= Igd::Pipe_control::QW_WRITE;
|
||||
tmp |= Igd::Pipe_control::STORE_DATA_INDEX;
|
||||
|
||||
cmd[1] = tmp;
|
||||
cmd[2] = (rcs.hw_status_page() + HWS_DATA) & 0xffffffff;
|
||||
cmd[2] = HWS_DATA;
|
||||
cmd[3] = 0; /* upper addr 0 */
|
||||
cmd[4] = _current_seqno & 0xffffffff;
|
||||
cmd[5] = _current_seqno >> 32;
|
||||
@ -767,7 +758,7 @@ struct Igd::Device
|
||||
Genode::uint32_t cmd[2] = {};
|
||||
Igd::Mi_user_interrupt ui;
|
||||
cmd[0] = ui.value;
|
||||
cmd[1] = MI_ARB_ON_OFF | MI_ARB_ENABLE;
|
||||
cmd[1] = Mi_arb_on_off(true).value;
|
||||
|
||||
for (size_t i = 0; i < CMD_NUM; i++) {
|
||||
advance += el.ring_append(cmd[i]);
|
||||
@ -779,9 +770,8 @@ struct Igd::Device
|
||||
/* gen8_emit_fini_breadcrumb_tail -> gen8_emit_wa_tail */
|
||||
enum { CMD_NUM = 2 };
|
||||
Genode::uint32_t cmd[2] = {};
|
||||
Igd::Mi_user_interrupt ui;
|
||||
cmd[0] = MI_ARB_CHECK;
|
||||
cmd[1] = MI_NOOP;
|
||||
cmd[0] = Mi_arb_check().value;
|
||||
cmd[1] = Mi_noop().value;
|
||||
|
||||
for (size_t i = 0; i < CMD_NUM; i++) {
|
||||
advance += el.ring_append(cmd[i]);
|
||||
@ -841,6 +831,11 @@ struct Igd::Device
|
||||
|
||||
int const port = _mmio.read<Igd::Mmio::EXECLIST_STATUS_RSCUNIT::Execlist_write_pointer>();
|
||||
|
||||
if (_mmio.read<Igd::Mmio::EXECLIST_STATUS_RSCUNIT::Execlist_0_valid>() ||
|
||||
_mmio.read<Igd::Mmio::EXECLIST_STATUS_RSCUNIT::Execlist_1_valid>())
|
||||
return;
|
||||
|
||||
|
||||
el.schedule(port);
|
||||
|
||||
uint32_t desc[4];
|
||||
@ -883,13 +878,6 @@ struct Igd::Device
|
||||
|
||||
_mmio.flush_gfx_tlb();
|
||||
|
||||
/*
|
||||
* XXX check if HWSP is shared across contexts and if not when
|
||||
* we actually need to write the register
|
||||
*/
|
||||
Mmio::HWS_PGA_RCSUNIT::access_t const addr = rcs.hw_status_page();
|
||||
_mmio.write_post<Igd::Mmio::HWS_PGA_RCSUNIT>(addr);
|
||||
|
||||
_submit_execlist(rcs);
|
||||
|
||||
_active_vgpu = gpu;
|
||||
@ -970,7 +958,7 @@ struct Igd::Device
|
||||
_mmio.execlist_status_dump();
|
||||
|
||||
_active_vgpu->rcs.context->dump();
|
||||
_active_vgpu->rcs.context->dump_hw_status_page();
|
||||
_hw_status_page->dump();
|
||||
Execlist &el = *_active_vgpu->rcs.execlist;
|
||||
el.ring_update_head(_active_vgpu->rcs.context->head_offset());
|
||||
el.ring_dump(4096, _active_vgpu->rcs.context->tail_offset() * 2,
|
||||
@ -1055,8 +1043,12 @@ struct Igd::Device
|
||||
|
||||
_clock_gating();
|
||||
|
||||
_mmio.dump();
|
||||
_mmio.context_status_pointer_dump();
|
||||
/* setup global hardware status page */
|
||||
_hw_status_ctx.construct(env.rm(), alloc, *this, 1, 0);
|
||||
_hw_status_page.construct(_hw_status_ctx->vaddr());
|
||||
|
||||
Mmio::HWS_PGA_RCSUNIT::access_t const addr = _hw_status_ctx->gmaddr();
|
||||
_mmio.write_post<Igd::Mmio::HWS_PGA_RCSUNIT>(addr);
|
||||
|
||||
/* read out slice, subslice, EUs information depending on platform */
|
||||
if (_info.platform == Device_info::Platform::BROADWELL) {
|
||||
@ -1084,6 +1076,9 @@ struct Igd::Device
|
||||
} else
|
||||
Genode::error("unsupported platform ", (int)_info.platform);
|
||||
|
||||
/* apply generation specific workarounds */
|
||||
apply_workarounds(_mmio, _info.generation);
|
||||
|
||||
_resources.timer().sigh(_watchdog_timeout_sigh);
|
||||
}
|
||||
|
||||
@ -1192,6 +1187,20 @@ struct Igd::Device
|
||||
return stepping_start <= stepping && stepping <= stepping_end;
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
** Hardware status page **
|
||||
**************************/
|
||||
|
||||
addr_t hw_status_page() const { return _hw_status_ctx->gmaddr(); }
|
||||
|
||||
uint64_t seqno() const
|
||||
{
|
||||
Utils::clflush((uint32_t*)(_hw_status_ctx->vaddr() + 0xc0));
|
||||
return *(uint32_t*)(_hw_status_ctx->vaddr() + 0xc0);
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** Vgpu handling **
|
||||
*******************/
|
||||
@ -1324,7 +1333,7 @@ struct Igd::Device
|
||||
uint32_t set_tiling(Ggtt::Offset const start, size_t const size,
|
||||
uint32_t const mode)
|
||||
{
|
||||
uint32_t const id = _mmio.find_free_fence();
|
||||
uint32_t const id = _get_free_fence();
|
||||
if (id == INVALID_FENCE) {
|
||||
Genode::warning("could not find free FENCE");
|
||||
return id;
|
||||
@ -1360,7 +1369,6 @@ struct Igd::Device
|
||||
Mmio::GT_0_INTERRUPT_IIR::access_t const v = _mmio.read<Mmio::GT_0_INTERRUPT_IIR>();
|
||||
|
||||
bool const ctx_switch = Mmio::GT_0_INTERRUPT_IIR::Cs_ctx_switch_interrupt::get(v);
|
||||
(void)ctx_switch;
|
||||
bool const user_complete = Mmio::GT_0_INTERRUPT_IIR::Cs_mi_user_interrupt::get(v);
|
||||
|
||||
if (v) { _clear_rcs_iir(v); }
|
||||
@ -1375,15 +1383,17 @@ struct Igd::Device
|
||||
bool const fault_valid = _mmio.fault_regs_valid();
|
||||
if (fault_valid) { Genode::error("FAULT_REG valid"); }
|
||||
|
||||
_mmio.update_context_status_pointer();
|
||||
if (ctx_switch)
|
||||
_mmio.update_context_status_pointer();
|
||||
|
||||
if (user_complete) {
|
||||
_unschedule_current_vgpu();
|
||||
_active_vgpu = nullptr;
|
||||
|
||||
if (notify_gpu) {
|
||||
if (!_notify_complete(notify_gpu))
|
||||
if (!_notify_complete(notify_gpu)) {
|
||||
_vgpu_list.enqueue(*notify_gpu);
|
||||
}
|
||||
}
|
||||
|
||||
/* keep the ball rolling... */
|
||||
@ -1540,7 +1550,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
throw Gpu::Session::Invalid_state();
|
||||
}
|
||||
|
||||
found = _vgpu.setup_ring_buffer(buffer.ppgtt_va, _device._ggtt->scratch_page());
|
||||
found = _vgpu.setup_ring_buffer(buffer.ppgtt_va);
|
||||
});
|
||||
|
||||
if (!found)
|
||||
@ -1751,6 +1761,9 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
return false;
|
||||
}
|
||||
|
||||
//XXX: support change of already fenced bo's fencing mode
|
||||
if (b->fenced) return true;
|
||||
|
||||
Igd::size_t const size = Genode::Dataspace_client(b->cap).size();
|
||||
Genode::uint32_t const fenced = _device.set_tiling(b->map.offset, size, mode);
|
||||
|
||||
@ -1910,7 +1923,16 @@ struct Main
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Main main(env); }
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
static Constructible<Main> main;
|
||||
try {
|
||||
main.construct(env);
|
||||
} catch (Igd::Resources::Initialization_failed) {
|
||||
Genode::warning("Intel GPU resources not found.");
|
||||
env.parent().exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Genode::size_t Component::stack_size() { return 32UL*1024*sizeof(long); }
|
||||
|
@ -1698,6 +1698,10 @@ class Igd::Mmio : public Genode::Mmio
|
||||
}
|
||||
}
|
||||
|
||||
struct Arbiter_control : Register<0xb004, 32> {
|
||||
struct Gaps_tsv_enable : Bitfield<7, 1> {};
|
||||
};
|
||||
|
||||
/*********************
|
||||
** DEBUG interface **
|
||||
*********************/
|
||||
|
@ -36,7 +36,7 @@ void Igd::Mmio::dump()
|
||||
log("0x2064 - IPEIR: ", Hex(read<IPEIR>()));
|
||||
log("0x2068 - IPEHR: ", Hex(read<IPEHR>()));
|
||||
log("0x206C - RCS_INSTDONE: ", Hex(read<RCS_INSTDONE>()));
|
||||
log("0x207C - RCS_ACTHD: ", Hex(read<RCS_ACTHD>()));
|
||||
log("0x2074 - RCS_ACTHD: ", Hex(read<RCS_ACTHD>()));
|
||||
log("0x2078 - DMA_FADD_PREF: ", Hex(read<DMA_FADD_PREF>()));
|
||||
log("0x207C - RCS_INSTDONE_1: ", Hex(read<RCS_INSTDONE_1>()));
|
||||
log("0x2094 - NOP_ID: ", Hex(read<NOP_ID>()));
|
||||
|
30
repos/os/src/drivers/gpu/intel/workarounds.h
Normal file
30
repos/os/src/drivers/gpu/intel/workarounds.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* \brief Generation specific workarounds
|
||||
* \author Sebastian Sumpf
|
||||
* \data 2021-09-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
#include <mmio.h>
|
||||
|
||||
namespace Igd {
|
||||
void apply_workarounds(Mmio &mmio, unsigned generation);
|
||||
}
|
||||
|
||||
void Igd::apply_workarounds(Mmio &mmio, unsigned generation)
|
||||
{
|
||||
/*
|
||||
* WaEnableGapsTsvCreditFix
|
||||
*
|
||||
* Sets the "GAPS TSV Credit fix ENABLE" of the RC arbiter bit that should be
|
||||
* set by BIOS for GEN9+. If this bit is not set, GPU will hang arbitrary
|
||||
* during batch buffer execution
|
||||
*/
|
||||
if (generation >= 9)
|
||||
mmio.write<Mmio::Arbiter_control::Gaps_tsv_enable>(1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user