Kernel/IPC: Implement MappedBuffer translation for HLE services that use the HLERequestContext architecture.
This commit is contained in:
@ -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
|
||||
|
Reference in New Issue
Block a user