mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-14 18:58:36 +12:00
rsx: Recover from invalid writes to CELL_GCM_NV4097_SET_INDEX_ARRAY_DMA
Also: Trigger a FIFO recovery when encountering an invalid method.
This commit is contained in:
parent
2eaf5df60b
commit
06017cb14e
7 changed files with 47 additions and 6 deletions
|
@ -87,6 +87,11 @@ namespace rsx
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FIFO_control::abort()
|
||||||
|
{
|
||||||
|
m_remaining_commands = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void FIFO_control::read(register_pair& data)
|
void FIFO_control::read(register_pair& data)
|
||||||
{
|
{
|
||||||
const u32 put = read_put();
|
const u32 put = read_put();
|
||||||
|
@ -392,11 +397,8 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case FIFO::FIFO_ERROR:
|
case FIFO::FIFO_ERROR:
|
||||||
{
|
{
|
||||||
// Error. Should reset the queue
|
|
||||||
LOG_ERROR(RSX, "FIFO error: possible desync event");
|
LOG_ERROR(RSX, "FIFO error: possible desync event");
|
||||||
fifo_ctrl->set_get(restore_point);
|
recover_fifo();
|
||||||
fifo_ret_addr = saved_fifo_ret;
|
|
||||||
std::this_thread::sleep_for(1ms);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,6 +565,13 @@ namespace rsx
|
||||||
if (auto method = methods[reg])
|
if (auto method = methods[reg])
|
||||||
{
|
{
|
||||||
method(this, reg, value);
|
method(this, reg, value);
|
||||||
|
|
||||||
|
if (invalid_command_interrupt_raised)
|
||||||
|
{
|
||||||
|
fifo_ctrl->abort();
|
||||||
|
recover_fifo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (fifo_ctrl->read_unsafe(command));
|
while (fifo_ctrl->read_unsafe(command));
|
||||||
|
|
|
@ -131,6 +131,7 @@ namespace rsx
|
||||||
void inc_get(bool wait);
|
void inc_get(bool wait);
|
||||||
void set_get(u32 get);
|
void set_get(u32 get);
|
||||||
void set_put(u32 put);
|
void set_put(u32 put);
|
||||||
|
void abort();
|
||||||
template <bool = true> u32 read_put();
|
template <bool = true> u32 read_put();
|
||||||
|
|
||||||
void read(register_pair& data);
|
void read(register_pair& data);
|
||||||
|
|
|
@ -2340,6 +2340,15 @@ namespace rsx
|
||||||
fifo_ctrl->sync_get();
|
fifo_ctrl->sync_get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thread::recover_fifo()
|
||||||
|
{
|
||||||
|
// Error. Should reset the queue
|
||||||
|
fifo_ctrl->set_get(restore_point);
|
||||||
|
fifo_ret_addr = saved_fifo_ret;
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
invalid_command_interrupt_raised = false;
|
||||||
|
}
|
||||||
|
|
||||||
void thread::read_barrier(u32 memory_address, u32 memory_range)
|
void thread::read_barrier(u32 memory_address, u32 memory_range)
|
||||||
{
|
{
|
||||||
zcull_ctrl->read_barrier(this, memory_address, memory_range);
|
zcull_ctrl->read_barrier(this, memory_address, memory_range);
|
||||||
|
|
|
@ -519,6 +519,7 @@ namespace rsx
|
||||||
atomic_t<bool> external_interrupt_lock{ false };
|
atomic_t<bool> external_interrupt_lock{ false };
|
||||||
atomic_t<bool> external_interrupt_ack{ false };
|
atomic_t<bool> external_interrupt_ack{ false };
|
||||||
void flush_fifo();
|
void flush_fifo();
|
||||||
|
void recover_fifo();
|
||||||
|
|
||||||
// Performance approximation counters
|
// Performance approximation counters
|
||||||
struct
|
struct
|
||||||
|
|
|
@ -21,8 +21,8 @@ rsx::index_array_type rsx::to_index_array_type(u8 in)
|
||||||
{
|
{
|
||||||
switch (in)
|
switch (in)
|
||||||
{
|
{
|
||||||
case 0: return rsx::index_array_type::u32;
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return rsx::index_array_type::u32;
|
||||||
case 1: return rsx::index_array_type::u16;
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return rsx::index_array_type::u16;
|
||||||
}
|
}
|
||||||
fmt::throw_exception("Unknown index array type %d" HERE, in);
|
fmt::throw_exception("Unknown index array type %d" HERE, in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -448,6 +448,13 @@ enum
|
||||||
CELL_GCM_SYSTEM_MODE_IOMAP_512MB = 1,
|
CELL_GCM_SYSTEM_MODE_IOMAP_512MB = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// Index Array Type
|
||||||
|
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0,
|
||||||
|
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
// GCM Texture
|
// GCM Texture
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -713,6 +713,19 @@ namespace rsx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_index_array_dma(thread* rsx, u32 reg, u32 arg)
|
||||||
|
{
|
||||||
|
// Check if either location or index type are invalid
|
||||||
|
if (arg & ~(CELL_GCM_LOCATION_MAIN | (CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 << 4)))
|
||||||
|
{
|
||||||
|
// Ignore invalid value, recover
|
||||||
|
method_registers.registers[reg] = method_registers.register_previous_value;
|
||||||
|
rsx->invalid_command_interrupt_raised = true;
|
||||||
|
|
||||||
|
LOG_ERROR(RSX, "Invalid NV4097_SET_INDEX_ARRAY_DMA value: 0x%x", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<u32 index>
|
template<u32 index>
|
||||||
struct set_texture_dirty_bit
|
struct set_texture_dirty_bit
|
||||||
{
|
{
|
||||||
|
@ -2911,6 +2924,7 @@ namespace rsx
|
||||||
bind_array<NV4097_SET_FOG_PARAMS, 1, 2, nv4097::set_ROP_state_dirty_bit>();
|
bind_array<NV4097_SET_FOG_PARAMS, 1, 2, nv4097::set_ROP_state_dirty_bit>();
|
||||||
bind_range<NV4097_SET_VIEWPORT_SCALE, 1, 3, nv4097::set_viewport_dirty_bit>();
|
bind_range<NV4097_SET_VIEWPORT_SCALE, 1, 3, nv4097::set_viewport_dirty_bit>();
|
||||||
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();
|
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();
|
||||||
|
bind<NV4097_SET_INDEX_ARRAY_DMA, nv4097::check_index_array_dma>();
|
||||||
|
|
||||||
//NV308A
|
//NV308A
|
||||||
bind_range<NV308A_COLOR, 1, 256, nv308a::color>();
|
bind_range<NV308A_COLOR, 1, 256, nv308a::color>();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue