From 5bf9218b327662d5a967ba747c1d660816656d04 Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 29 Sep 2026 20:58:57 +0400 Subject: [PATCH] ampr: keep commands in one append-ordered sequence --- src/libs/libAmpr.cpp | 259 +++++++++++++++++-------------------------- 1 file changed, 103 insertions(+), 156 deletions(-) diff --git a/src/libs/libAmpr.cpp b/src/libs/libAmpr.cpp index d98241c9e..a38787129 100644 --- a/src/libs/libAmpr.cpp +++ b/src/libs/libAmpr.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef min @@ -705,41 +706,38 @@ struct CommandBufferState { bool header_validated = false; bool buffer_validated = false; struct ReadFileCommand { - uint64_t record_offset = 0; - uint32_t file_id = 0; - uint64_t destination = 0; - uint64_t size = 0; - uint64_t file_offset = 0; + uint32_t file_id = 0; + uint64_t destination = 0; + uint64_t size = 0; + uint64_t file_offset = 0; }; struct KernelEventCommand { - uint64_t record_offset = 0; - uint64_t eq = 0; - int32_t id = 0; - uint64_t data = 0; + uint64_t eq = 0; + int32_t id = 0; + uint64_t data = 0; }; struct WriteAddressCommand { - uint64_t record_offset = 0; - uint64_t address = 0; - uint64_t value = 0; + uint64_t address = 0; + uint64_t value = 0; }; struct AmmMapCommand { - uint64_t record_offset = 0; - AmmCommandKind kind = AmmCommandKind::MapAuto; - uint64_t va = 0; - uint64_t dmem_offset = 0; - uint64_t size = 0; - int32_t type = 0; - int32_t prot = 0; - uint8_t gpu_mask_id = 0; + AmmCommandKind kind = AmmCommandKind::MapAuto; + uint64_t va = 0; + uint64_t dmem_offset = 0; + uint64_t size = 0; + int32_t type = 0; + int32_t prot = 0; + uint8_t gpu_mask_id = 0; }; - std::vector read_file_commands; - std::vector kernel_event_commands; - std::vector write_address_commands; - std::vector amm_map_commands; - bool gather_scatter_valid = false; - uint32_t gather_scatter_file_id = 0; - uint64_t gather_scatter_destination = 0; - uint64_t gather_scatter_file_offset = 0; + struct Command { + uint64_t record_offset; + std::variant data; + }; + std::vector commands; + bool gather_scatter_valid = false; + uint32_t gather_scatter_file_id = 0; + uint64_t gather_scatter_destination = 0; + uint64_t gather_scatter_file_offset = 0; }; struct AmmUsageStatsData { @@ -757,11 +755,6 @@ static std::unordered_map g_command_buffers; static std::unordered_map g_command_buffer_aliases; using CommandBufferIterator = std::unordered_map::iterator; -static bool HasQueuedCommands(const CommandBufferState& state) { - return !state.read_file_commands.empty() || !state.kernel_event_commands.empty() || - !state.write_address_commands.empty() || !state.amm_map_commands.empty(); -} - static void RegisterCommandBufferAliasLocked(uint64_t command_buffer, uint64_t buffer) { for (auto it = g_command_buffer_aliases.begin(); it != g_command_buffer_aliases.end();) { if (it->second == command_buffer) { @@ -950,7 +943,7 @@ static bool UpdateCommandBufferTypeFlags(uint64_t command_buffer, uint32_t set_b static std::unordered_map::iterator ResolveCommandBufferStateLocked(uint64_t command_buffer) { auto it = g_command_buffers.find(command_buffer); - if (it != g_command_buffers.end() && HasQueuedCommands(it->second)) { + if (it != g_command_buffers.end() && !it->second.commands.empty()) { return it; } @@ -999,10 +992,7 @@ static bool WriteCommandBufferPointers(uint64_t command_buffer, uint64_t buffer, state.write_offset = write_offset; state.header_validated = true; state.buffer_validated = false; - state.read_file_commands.clear(); - state.kernel_event_commands.clear(); - state.write_address_commands.clear(); - state.amm_map_commands.clear(); + state.commands.clear(); state.gather_scatter_valid = false; state.gather_scatter_file_id = 0; state.gather_scatter_destination = 0; @@ -1107,7 +1097,8 @@ static bool AppendReadFileRecord(uint64_t command_buffer, uint8_t opcode, uint32 std::memset(reinterpret_cast(state.buffer + record_offset), 0, static_cast(record_size)); std::memcpy(reinterpret_cast(state.buffer + record_offset), &opcode, sizeof(opcode)); - state.read_file_commands.push_back({record_offset, file_id, destination, size, file_offset}); + state.commands.push_back({record_offset, CommandBufferState::ReadFileCommand { + file_id, destination, size, file_offset}}); if (!CommitCommandBufferRecord(command_buffer, &state, record_size)) { return false; } @@ -1145,7 +1136,8 @@ static bool AppendKernelEventRecord(uint64_t command_buffer, uint64_t eq, int32_ const auto record_offset = state.write_offset; std::memcpy(reinterpret_cast(state.buffer + record_offset), record.data(), record.size()); - state.kernel_event_commands.push_back({record_offset, eq, id, data}); + state.commands.push_back( + {record_offset, CommandBufferState::KernelEventCommand {eq, id, data}}); return CommitCommandBufferRecord(command_buffer, &state, KERNEL_EVENT_RECORD_SIZE); } @@ -1165,7 +1157,8 @@ static bool AppendWriteAddressRecord(uint64_t command_buffer, uint64_t address, const auto record_offset = state.write_offset; std::memset(reinterpret_cast(state.buffer + record_offset), 0, static_cast(record_size)); - state.write_address_commands.push_back({record_offset, address, value}); + state.commands.push_back( + {record_offset, CommandBufferState::WriteAddressCommand {address, value}}); return CommitCommandBufferRecord(command_buffer, &state, record_size); } @@ -1239,11 +1232,9 @@ static bool AppendAmmMapRecord(uint64_t command_ return false; } - auto record = cmd; - record.record_offset = state.write_offset; auto* record_addr = reinterpret_cast(state.buffer + state.write_offset); std::memset(record_addr, 0, static_cast(record_size)); - state.amm_map_commands.push_back(record); + state.commands.push_back({state.write_offset, cmd}); return CommitCommandBufferRecord(command_buffer, &state, record_size); } @@ -1264,121 +1255,77 @@ static int ExecuteAprCommandBuffer(uint64_t command_buffer, int32_t* execution_r return LibKernel::KERNEL_ERROR_EFAULT; } - enum class CommandKind { - ReadFile, - KernelEvent, - WriteAddress, - AmmMap, - }; - - struct OrderedCommand { - uint64_t record_offset = 0; - CommandKind kind = CommandKind::ReadFile; - size_t index = 0; - }; - - std::vector ordered; - ordered.reserve(state.read_file_commands.size() + state.kernel_event_commands.size() + - state.write_address_commands.size() + state.amm_map_commands.size()); - for (size_t i = 0; i < state.read_file_commands.size(); i++) { - if (state.read_file_commands[i].record_offset < state.write_offset) { - ordered.push_back( - {state.read_file_commands[i].record_offset, CommandKind::ReadFile, i}); + for (const auto& entry: state.commands) { + if (entry.record_offset >= state.write_offset) { + break; } - } - for (size_t i = 0; i < state.kernel_event_commands.size(); i++) { - if (state.kernel_event_commands[i].record_offset < state.write_offset) { - ordered.push_back( - {state.kernel_event_commands[i].record_offset, CommandKind::KernelEvent, i}); - } - } - for (size_t i = 0; i < state.write_address_commands.size(); i++) { - if (state.write_address_commands[i].record_offset < state.write_offset) { - ordered.push_back( - {state.write_address_commands[i].record_offset, CommandKind::WriteAddress, i}); - } - } - for (size_t i = 0; i < state.amm_map_commands.size(); i++) { - if (state.amm_map_commands[i].record_offset < state.write_offset) { - ordered.push_back({state.amm_map_commands[i].record_offset, CommandKind::AmmMap, i}); - } - } + if (const auto* payload = std::get_if(&entry.data)) { + const auto& command = *payload; + std::string host_path; + if (!AprShared::TryGetHostPath(command.file_id, &host_path)) { + LOGF("\tAPR submit failed for unknown file id: 0x%08" PRIx32 "\n", command.file_id); + *execution_result = LibKernel::KERNEL_ERROR_ENOENT; + *error_offset = static_cast(entry.record_offset); + return OK; + } - std::sort(ordered.begin(), ordered.end(), [](const OrderedCommand& a, const OrderedCommand& b) { - return a.record_offset < b.record_offset; - }); + uint64_t bytes_read = 0; + auto result = ReadHostFileToGuest(host_path, command.file_offset, command.destination, + command.size, &bytes_read); + if (result != OK) { + LOGF("\tAPR submit read failed: id=0x%08" PRIx32 ", result=0x%08" PRIx32 + ", path=%s\n", + command.file_id, static_cast(result), host_path.c_str()); + *execution_result = result; + *error_offset = static_cast(entry.record_offset); + return OK; + } + } else if (const auto* payload = + std::get_if(&entry.data)) { + const auto& command = *payload; + const auto eq = static_cast(command.eq); + auto result = LibKernel::EventQueue::KernelTriggerUserEvent( + eq, command.id, reinterpret_cast(command.data)); + if (result != OK) { + LOGF("\tAPR submit event failed: eq=0x%016" PRIx64 ", id=%" PRId32 + ", result=0x%08" PRIx32 "\n", + command.eq, command.id, static_cast(result)); + *execution_result = result; + *error_offset = static_cast(entry.record_offset); + return OK; + } + } else if (const auto* payload = + std::get_if(&entry.data)) { + const auto& command = *payload; + if (!AprShared::WriteGuest(command.address, command.value)) { + LOGF("\tAMPR submit write-address failed: address=0x%016" PRIx64 + " value=0x%016" PRIx64 "\n", + command.address, command.value); + *execution_result = LibKernel::KERNEL_ERROR_EFAULT; + *error_offset = static_cast(entry.record_offset); + return OK; + } + } else if (const auto* payload = + std::get_if(&entry.data)) { + const auto& command = *payload; + int result = OK; + if (command.kind == AmmCommandKind::Unmap) { + result = LibKernel::Memory::KernelMunmap(command.va, command.size); + } else { + result = ExecuteAmmMapCommand(command); + } - for (const auto& entry: ordered) { - switch (entry.kind) { - case CommandKind::ReadFile: { - const auto& command = state.read_file_commands[entry.index]; - std::string host_path; - if (!AprShared::TryGetHostPath(command.file_id, &host_path)) { - LOGF("\tAPR submit failed for unknown file id: 0x%08" PRIx32 "\n", - command.file_id); - *execution_result = LibKernel::KERNEL_ERROR_ENOENT; - *error_offset = static_cast(command.record_offset); - return OK; - } - - uint64_t bytes_read = 0; - auto result = ReadHostFileToGuest(host_path, command.file_offset, - command.destination, command.size, &bytes_read); - if (result != OK) { - LOGF("\tAPR submit read failed: id=0x%08" PRIx32 ", result=0x%08" PRIx32 - ", path=%s\n", - command.file_id, static_cast(result), host_path.c_str()); - *execution_result = result; - *error_offset = static_cast(command.record_offset); - return OK; - } - } break; - case CommandKind::KernelEvent: { - const auto& command = state.kernel_event_commands[entry.index]; - const auto eq = static_cast(command.eq); - auto result = LibKernel::EventQueue::KernelTriggerUserEvent( - eq, command.id, reinterpret_cast(command.data)); - if (result != OK) { - LOGF("\tAPR submit event failed: eq=0x%016" PRIx64 ", id=%" PRId32 - ", result=0x%08" PRIx32 "\n", - command.eq, command.id, static_cast(result)); - *execution_result = result; - *error_offset = static_cast(command.record_offset); - return OK; - } - } break; - case CommandKind::WriteAddress: { - const auto& command = state.write_address_commands[entry.index]; - if (!AprShared::WriteGuest(command.address, command.value)) { - LOGF("\tAMPR submit write-address failed: address=0x%016" PRIx64 - " value=0x%016" PRIx64 "\n", - command.address, command.value); - *execution_result = LibKernel::KERNEL_ERROR_EFAULT; - *error_offset = static_cast(command.record_offset); - return OK; - } - } break; - case CommandKind::AmmMap: { - const auto& command = state.amm_map_commands[entry.index]; - int result = OK; - if (command.kind == AmmCommandKind::Unmap) { - result = LibKernel::Memory::KernelMunmap(command.va, command.size); - } else { - result = ExecuteAmmMapCommand(command); - } - - if (result != OK) { - LOGF("\tAMM submit command failed: kind=%u va=0x%016" PRIx64 - " dmem=0x%016" PRIx64 " size=0x%016" PRIx64 " type=%" PRId32 - " prot=0x%08" PRIx32 " result=0x%08" PRIx32 "\n", - static_cast(command.kind), command.va, command.dmem_offset, - command.size, command.type, static_cast(command.prot), - static_cast(result)); - *execution_result = result; - *error_offset = static_cast(command.record_offset); - return OK; - } - } break; + if (result != OK) { + LOGF("\tAMM submit command failed: kind=%u va=0x%016" PRIx64 " dmem=0x%016" PRIx64 + " size=0x%016" PRIx64 " type=%" PRId32 " prot=0x%08" PRIx32 + " result=0x%08" PRIx32 "\n", + static_cast(command.kind), command.va, command.dmem_offset, + command.size, command.type, static_cast(command.prot), + static_cast(result)); + *execution_result = result; + *error_offset = static_cast(entry.record_offset); + return OK; + } } }