mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 11:26:56 +02:00
ampr: fix APR completion loss in 768-byte read batches
Co-authored-by: Chai T <ct@talnikar.in>
This commit is contained in:
@@ -898,6 +898,11 @@ void CheckAmprOrdering(Loader::SymbolDatabase &symbols, uint32_t file_id) {
|
||||
using WriteCounter = int (KYTY_SYSV_ABI *)(void *, uint8_t, uint8_t, uint64_t,
|
||||
uint8_t, uint32_t);
|
||||
using WriteAddress = int (KYTY_SYSV_ABI *)(void *, volatile uint64_t *, uint64_t);
|
||||
using WriteImmediately = int (KYTY_SYSV_ABI *)(void *, volatile uint64_t *, uint64_t,
|
||||
uint32_t);
|
||||
using MeasureWriteAddress = uint64_t (KYTY_SYSV_ABI *)(volatile uint64_t *, uint64_t);
|
||||
using MeasureWriteImmediately = uint64_t (KYTY_SYSV_ABI *)(volatile uint64_t *, uint64_t,
|
||||
uint32_t);
|
||||
using ReadFile = int (KYTY_SYSV_ABI *)(void *, uint64_t, uint64_t, uint32_t,
|
||||
void *, uint64_t, uint64_t);
|
||||
using WriteKernelEvent = int (KYTY_SYSV_ABI *)(void *, uint64_t, uint64_t, uint64_t,
|
||||
@@ -916,6 +921,9 @@ void CheckAmprOrdering(Loader::SymbolDatabase &symbols, uint32_t file_id) {
|
||||
const auto wait_counter = reinterpret_cast<WaitCounter>(find("cQb8Zr8Q0Y0"));
|
||||
const auto write_counter = reinterpret_cast<WriteCounter>(find("jK+yuYCI7MA"));
|
||||
const auto write_address = reinterpret_cast<WriteAddress>(find("sJXyWHjP-F8"));
|
||||
const auto write_immediately = reinterpret_cast<WriteImmediately>(find("j0+3uJMxYJY"));
|
||||
const auto measure_write_address = reinterpret_cast<MeasureWriteAddress>(find("C+IEj+BsAFM"));
|
||||
const auto measure_write_immediately = reinterpret_cast<MeasureWriteImmediately>(find("4fgtGfXDrFc"));
|
||||
const auto read_file = reinterpret_cast<ReadFile>(find("mQ16-QdKv7k"));
|
||||
const auto write_event = reinterpret_cast<WriteKernelEvent>(find("H896Pt-yB4I"));
|
||||
const auto submit_apr = reinterpret_cast<SubmitApr>(find("ASoW5WE-UPo"));
|
||||
@@ -927,7 +935,7 @@ void CheckAmprOrdering(Loader::SymbolDatabase &symbols, uint32_t file_id) {
|
||||
std::array<uint32_t, 256> data {};
|
||||
};
|
||||
std::array<Buffer, 4> buffers;
|
||||
const auto reset = [&](size_t apr_count) {
|
||||
const auto reset = [&](size_t apr_count, uint32_t data_size = sizeof(Buffer::data)) {
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
auto &buffer = buffers[i];
|
||||
construct(buffer.header.data());
|
||||
@@ -936,10 +944,60 @@ void CheckAmprOrdering(Loader::SymbolDatabase &symbols, uint32_t file_id) {
|
||||
} else {
|
||||
construct_amm(buffer.header.data());
|
||||
}
|
||||
Check(set_buffer(buffer.header.data(), buffer.data.data(), sizeof(buffer.data)) == OK,
|
||||
Check(set_buffer(buffer.header.data(), buffer.data.data(), data_size) == OK,
|
||||
"initialize AMPR command buffer");
|
||||
}
|
||||
};
|
||||
struct LiteralWrite { uint64_t value; uint32_t size; };
|
||||
constexpr std::array literal_writes {
|
||||
LiteralWrite{0, 8}, LiteralWrite{3, 8}, LiteralWrite{4, 12},
|
||||
LiteralWrite{(uint64_t{1} << 34) - 1, 12},
|
||||
LiteralWrite{uint64_t{1} << 34, 16}, LiteralWrite{UINT64_MAX, 16}};
|
||||
for (const auto &literal : literal_writes) {
|
||||
for (const bool immediately : std::array{false, true}) {
|
||||
reset(1, literal.size);
|
||||
auto *command_buffer = buffers[0].header.data();
|
||||
uint64_t fence = ~literal.value;
|
||||
const auto append = [&](uint64_t value) {
|
||||
return immediately ? write_immediately(command_buffer, &fence, value, 1)
|
||||
: write_address(command_buffer, &fence, value);
|
||||
};
|
||||
Check(measure_write_address(&fence, literal.value) == literal.size &&
|
||||
measure_write_immediately(&fence, literal.value, 1) == literal.size &&
|
||||
append(literal.value) == OK && offset(command_buffer) == literal.size,
|
||||
"literal write fits exactly its measured command size");
|
||||
Check(append(~literal.value) == Libs::LibKernel::KERNEL_ERROR_EBUSY &&
|
||||
offset(command_buffer) == literal.size,
|
||||
"rejected write preserves the full command buffer offset");
|
||||
Result result {1234, 5678};
|
||||
uint32_t submission = 0;
|
||||
Check(submit_apr(command_buffer, 3, &result, &submission) == OK &&
|
||||
wait_apr(submission) == OK && result.result == OK &&
|
||||
fence == literal.value,
|
||||
"bounded write preserves all sixty-four literal bits");
|
||||
}
|
||||
}
|
||||
reset(1, 768);
|
||||
std::array<std::array<char, 3>, 16> batch_output {};
|
||||
std::array<uint64_t, 16> batch_fences {};
|
||||
auto *batch = buffers[0].header.data();
|
||||
for (size_t i = 0; i < batch_fences.size(); ++i) {
|
||||
Check(read_file(batch, reinterpret_cast<uint64_t>(&buffers[0].header[3]),
|
||||
reinterpret_cast<uint64_t>(&buffers[0].header[4]), file_id,
|
||||
batch_output[i].data(), batch_output[i].size(), 0) == OK &&
|
||||
write_address(batch, &batch_fences[i], i + 1) == OK,
|
||||
"sixteen APR read/fence pairs fit the guest's 768-byte command buffer");
|
||||
}
|
||||
Result batch_result {1234, 5678};
|
||||
uint32_t batch_submission = 0;
|
||||
Check(submit_apr(batch, 3, &batch_result, &batch_submission) == OK &&
|
||||
wait_apr(batch_submission) == OK && batch_result.result == OK,
|
||||
"complete the bounded APR read batch");
|
||||
for (size_t i = 0; i < batch_fences.size(); ++i) {
|
||||
Check(batch_fences[i] == i + 1 &&
|
||||
std::memcmp(batch_output[i].data(), "APR", 3) == 0,
|
||||
"every read publishes its data and completion, including requests fourteen and fifteen");
|
||||
}
|
||||
// WaitCompare order: ==, unsigned >/<, !=, wrapped >=, signed >/<.
|
||||
struct Comparison { uint8_t compare; uint64_t blocked, reference, released; };
|
||||
constexpr std::array comparisons {
|
||||
|
||||
Reference in New Issue
Block a user