Kernel/IPC: Implement MappedBuffer translation for HLE services that use the HLERequestContext architecture.

This commit is contained in:
wwylele
2017-07-14 22:24:57 +03:00
parent 4071da5012
commit 3ecf650bf9
2 changed files with 83 additions and 0 deletions

View File

@ -63,6 +63,35 @@ protected:
std::vector<SharedPtr<ServerSession>> connected_sessions;
};
class MappedBuffer {
public:
MappedBuffer(const Process& process, u32 descriptor, VAddr address, u32 id);
// interface for service
void Read(void* dest_buffer, size_t offset, size_t size);
void Write(const void* src_buffer, size_t offset, size_t size);
size_t GetSize() const {
return size;
}
// interface for ipc helper
u32 GenerateDescriptor() const {
return IPC::MappedBufferDesc(size, perms);
}
u32 GetId() const {
return id;
}
private:
friend class HLERequestContext;
u32 id;
VAddr address;
const Process* process;
size_t size;
IPC::MappedBufferPermissions perms;
};
/**
* Class containing information about an in-flight IPC request being handled by an HLE service
* implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and
@ -81,6 +110,17 @@ protected:
* The end result is similar to just giving services their own real handle tables, but since these
* ids are local to a specific context, it avoids requiring services to manage handles for objects
* across multiple calls and ensuring that unneeded handles are cleaned up.
*
* HLE mapped buffer protocol
* ==========================
*
* HLE services don't have their own virtual memory space, a tweaked protocol is used to simulate
* memory mapping. The kernel will wrap the incoming buffers into a memory interface on which HLE
* services can operate, and insert a id in the buffer where the vaddr would normally be. The
* service then calls GetMappedBuffer with that id to get the memory interface. On response, like
* real services pushing back the mapped buffer address to unmap it, HLE services push back the
* id of the memory interface and let kernel convert it back to client vaddr. No real unmapping is
* needed in this case, though.
*/
class HLERequestContext {
public:
@ -131,6 +171,12 @@ public:
*/
void AddStaticBuffer(u8 buffer_id, std::vector<u8> data);
/**
* Gets a memory interface by the id from the request command buffer. See the "HLE mapped buffer
* protocol" section in the class documentation for more details.
*/
MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf);
/// Populates this context with data from the requesting process/thread.
ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process,
HandleTable& src_table);
@ -145,6 +191,8 @@ private:
boost::container::small_vector<SharedPtr<Object>, 8> request_handles;
// The static buffers will be created when the IPC request is translated.
std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers;
// The mapped buffers will be created when the IPC request is translated
boost::container::small_vector<MappedBuffer, 8> request_mapped_buffers;
};
} // namespace Kernel