IPC refactor part 3+4: New server HIPC message processor (#4188)
* IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization * Make types match on calls to AlignUp/AlignDown * Formatting * Address some PR feedback * Move BitfieldExtensions to Ryujinx.Common.Utilities and consolidate implementations * Rename Reader/Writer to SpanReader/SpanWriter and move to Ryujinx.Common.Memory * Implement EventType * Address more PR feedback * Log request processing errors since they are not normal * Rename waitable to multiwait and add missing lock * PR feedback * Ac_K PR feedback
This commit is contained in:
parent
c6a139a6e7
commit
08831eecf7
213 changed files with 9762 additions and 1010 deletions
128
Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs
Normal file
128
Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using Ryujinx.Horizon.Common;
|
||||
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
||||
{
|
||||
static class CmifMessage
|
||||
{
|
||||
public const uint CmifInHeaderMagic = 0x49434653; // SFCI
|
||||
public const uint CmifOutHeaderMagic = 0x4f434653; // SFCO
|
||||
|
||||
public static CmifRequest CreateRequest(Span<byte> output, CmifRequestFormat format)
|
||||
{
|
||||
int totalSize = 16;
|
||||
|
||||
if (format.ObjectId != 0)
|
||||
{
|
||||
totalSize += Unsafe.SizeOf<CmifDomainInHeader>() + format.ObjectsCount * sizeof(int);
|
||||
}
|
||||
|
||||
totalSize += Unsafe.SizeOf<CmifInHeader>() + format.DataSize;
|
||||
totalSize = (totalSize + 1) & ~1;
|
||||
int outPointerSizeTableOffset = totalSize;
|
||||
int outPointerSizeTableSize = format.OutAutoBuffersCount + format.OutPointersCount;
|
||||
totalSize += sizeof(ushort) * outPointerSizeTableSize;
|
||||
int rawDataSizeInWords = (totalSize + sizeof(uint) - 1) / sizeof(uint);
|
||||
|
||||
CmifRequest request = new CmifRequest();
|
||||
|
||||
request.Hipc = HipcMessage.WriteMessage(output, new HipcMetadata()
|
||||
{
|
||||
Type = format.Context != 0 ? (int)CommandType.RequestWithContext : (int)CommandType.Request,
|
||||
SendStaticsCount = format.InAutoBuffersCount + format.InPointersCount,
|
||||
SendBuffersCount = format.InAutoBuffersCount + format.InBuffersCount,
|
||||
ReceiveBuffersCount = format.OutAutoBuffersCount + format.OutBuffersCount,
|
||||
ExchangeBuffersCount = format.InOutBuffersCount,
|
||||
DataWordsCount = rawDataSizeInWords,
|
||||
ReceiveStaticsCount = outPointerSizeTableSize + format.OutFixedPointersCount,
|
||||
SendPid = format.SendPid,
|
||||
CopyHandlesCount = format.HandlesCount,
|
||||
MoveHandlesCount = 0
|
||||
});
|
||||
|
||||
Span<uint> data = request.Hipc.DataWords;
|
||||
|
||||
if (format.ObjectId != 0)
|
||||
{
|
||||
ref CmifDomainInHeader domainHeader = ref MemoryMarshal.Cast<uint, CmifDomainInHeader>(data)[0];
|
||||
|
||||
int payloadSize = Unsafe.SizeOf<CmifInHeader>() + format.DataSize;
|
||||
|
||||
domainHeader = new CmifDomainInHeader()
|
||||
{
|
||||
Type = CmifDomainRequestType.SendMessage,
|
||||
ObjectsCount = (byte)format.ObjectsCount,
|
||||
DataSize = (ushort)payloadSize,
|
||||
ObjectId = format.ObjectId,
|
||||
Padding = 0,
|
||||
Token = format.Context
|
||||
};
|
||||
|
||||
data = data.Slice(Unsafe.SizeOf<CmifDomainInHeader>() / sizeof(uint));
|
||||
|
||||
request.Objects = data.Slice((payloadSize + sizeof(uint) - 1) / sizeof(uint));
|
||||
}
|
||||
|
||||
ref CmifInHeader header = ref MemoryMarshal.Cast<uint, CmifInHeader>(data)[0];
|
||||
|
||||
header = new CmifInHeader()
|
||||
{
|
||||
Magic = CmifInHeaderMagic,
|
||||
Version = format.Context != 0 ? 1u : 0u,
|
||||
CommandId = format.RequestId,
|
||||
Token = format.ObjectId != 0 ? 0u : format.Context
|
||||
};
|
||||
|
||||
request.Data = MemoryMarshal.Cast<uint, byte>(data).Slice(Unsafe.SizeOf<CmifInHeader>());
|
||||
|
||||
int paddingSizeBefore = (rawDataSizeInWords - request.Hipc.DataWords.Length) * sizeof(uint);
|
||||
|
||||
Span<byte> outPointerTable = MemoryMarshal.Cast<uint, byte>(request.Hipc.DataWords).Slice(outPointerSizeTableOffset - paddingSizeBefore);
|
||||
request.OutPointerSizes = MemoryMarshal.Cast<byte, ushort>(outPointerTable);
|
||||
request.ServerPointerSize = format.ServerPointerSize;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Result ParseResponse(out CmifResponse response, Span<byte> input, bool isDomain, int size)
|
||||
{
|
||||
HipcMessage responseMessage = new HipcMessage(input);
|
||||
|
||||
Span<byte> data = MemoryMarshal.Cast<uint, byte>(responseMessage.Data.DataWords);
|
||||
Span<uint> objects = Span<uint>.Empty;
|
||||
|
||||
if (isDomain)
|
||||
{
|
||||
data = data.Slice(Unsafe.SizeOf<CmifDomainOutHeader>());
|
||||
objects = MemoryMarshal.Cast<byte, uint>(data.Slice(Unsafe.SizeOf<CmifOutHeader>() + size));
|
||||
}
|
||||
|
||||
CmifOutHeader header = MemoryMarshal.Cast<byte, CmifOutHeader>(data)[0];
|
||||
|
||||
if (header.Magic != CmifOutHeaderMagic)
|
||||
{
|
||||
response = default;
|
||||
return SfResult.InvalidOutHeader;
|
||||
}
|
||||
|
||||
if (header.Result.IsFailure)
|
||||
{
|
||||
response = default;
|
||||
return header.Result;
|
||||
}
|
||||
|
||||
response = new CmifResponse()
|
||||
{
|
||||
Data = data.Slice(Unsafe.SizeOf<CmifOutHeader>()),
|
||||
Objects = objects,
|
||||
CopyHandles = responseMessage.Data.CopyHandles,
|
||||
MoveHandles = responseMessage.Data.MoveHandles
|
||||
};
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue