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

The real kernel requires services to set up their static buffer targets ahead of time. This implementation does not require that and will simply create the storage for the buffers as they are processed in the incoming IPC request.

Static buffers are kept in an unordered_map keyed by their buffer id, and are written into the already-setup area of the request thread when responding an IPC request.

This fixes a regression (crash) introduced in #2992.

This PR introduces more warnings due to the [[deprecated]] attribute being added to void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); and VAddr PopStaticBuffer(size_t* data_size);
This commit is contained in:
Subv 2017-11-05 12:50:22 -05:00
parent 4fc0448093
commit c9c1ba0952
10 changed files with 113 additions and 40 deletions

View file

@ -8,6 +8,7 @@
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "core/hle/ipc.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
@ -117,7 +118,8 @@ public:
void PushCurrentPIDHandle();
void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id);
[[deprecated]] void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id);
void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id);
void PushMappedBuffer(VAddr buffer_vaddr, size_t size, MappedBufferPermissions perms);
};
@ -195,6 +197,16 @@ inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8
Push(buffer_vaddr);
}
inline void RequestBuilder::PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id) {
ASSERT_MSG(buffer_id < MAX_STATIC_BUFFERS, "Invalid static buffer id");
Push(StaticBufferDesc(buffer.size(), buffer_id));
// This address will be replaced by the correct static buffer address during IPC translation.
Push<VAddr>(0xDEADC0DE);
context->AddStaticBuffer(buffer_id, buffer);
}
inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size,
MappedBufferPermissions perms) {
Push(MappedBufferDesc(size, perms));
@ -295,17 +307,23 @@ public:
* @brief Pops the static buffer vaddr
* @return The virtual address of the buffer
* @param[out] data_size If non-null, the pointed value will be set to the size of the data
* @param[out] useStaticBuffersToGetVaddr Indicates if we should read the vaddr from the static
* buffers (which is the correct thing to do, but no service presently implement it) instead of
* using the same value as the process who sent the request
* given by the source process
*
* Static buffers must be set up before any IPC request using those is sent.
* In real services, static buffers must be set up before any IPC request using those is sent.
* It is the duty of the process (usually services) to allocate and set up the receiving static
* buffer information
* buffer information. Our HLE services do not need to set up the buffers beforehand.
* Please note that the setup uses virtual addresses.
*/
VAddr PopStaticBuffer(size_t* data_size = nullptr, bool useStaticBuffersToGetVaddr = false);
[[deprecated]] VAddr PopStaticBuffer(size_t* data_size);
/**
* @brief Pops a static buffer from the IPC request buffer.
* @return The buffer that was copied from the IPC request originator.
*
* In real services, static buffers must be set up before any IPC request using those is sent.
* It is the duty of the process (usually services) to allocate and set up the receiving static
* buffer information. Our HLE services do not need to set up the buffers beforehand.
*/
const std::vector<u8>& PopStaticBuffer();
/**
* @brief Pops the mapped buffer vaddr
@ -451,21 +469,21 @@ inline std::tuple<Kernel::SharedPtr<T>...> RequestParser::PopObjects() {
std::index_sequence_for<T...>{});
}
inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) {
inline VAddr RequestParser::PopStaticBuffer(size_t* data_size) {
const u32 sbuffer_descriptor = Pop<u32>();
StaticBufferDescInfo bufferInfo{sbuffer_descriptor};
if (data_size != nullptr)
*data_size = bufferInfo.size;
if (!useStaticBuffersToGetVaddr)
return Pop<VAddr>();
else {
ASSERT_MSG(0, "remove the assert if multiprocess/IPC translation are implemented.");
// The buffer has already been copied to the static buffer by the kernel during
// translation
Pop<VAddr>(); // Pop the calling process buffer address
// and get the vaddr from the static buffers
return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1];
}
return Pop<VAddr>();
}
inline const std::vector<u8>& RequestParser::PopStaticBuffer() {
const u32 sbuffer_descriptor = Pop<u32>();
// Pop the address from the incoming request buffer
Pop<VAddr>();
StaticBufferDescInfo buffer_info{sbuffer_descriptor};
return context->GetStaticBuffer(buffer_info.buffer_id);
}
inline VAddr RequestParser::PopMappedBuffer(size_t* data_size,