ipc.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2016 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include "common/common_types.h"
  6. #include "core/hle/kernel/thread.h"
  7. #include "core/memory.h"
  8. namespace Kernel {
  9. /// Offset into command buffer of header
  10. static const int kCommandHeaderOffset = 0x80;
  11. /**
  12. * Returns a pointer to the command buffer in the current thread's TLS
  13. * TODO(Subv): This is not entirely correct, the command buffer should be copied from
  14. * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to
  15. * the service handler process' memory.
  16. * @param offset Optional offset into command buffer
  17. * @param offset Optional offset into command buffer (in bytes)
  18. * @return Pointer to command buffer
  19. */
  20. inline u32* GetCommandBuffer(const int offset = 0) {
  21. return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
  22. offset);
  23. }
  24. /// Offset into static buffers, relative to command buffer header
  25. static const int kStaticBuffersOffset = 0x100;
  26. /**
  27. * Returns a pointer to the static buffers area in the current thread's TLS
  28. * TODO(Subv): cf. GetCommandBuffer
  29. * @param offset Optional offset into static buffers area (in bytes)
  30. * @return Pointer to static buffers area
  31. */
  32. inline u32* GetStaticBuffers(const int offset = 0) {
  33. return GetCommandBuffer(kStaticBuffersOffset + offset);
  34. }
  35. }
  36. namespace IPC {
  37. enum DescriptorType : u32 {
  38. // Buffer related desciptors types (mask : 0x0F)
  39. StaticBuffer = 0x02,
  40. PXIBuffer = 0x04,
  41. MappedBuffer = 0x08,
  42. // Handle related descriptors types (mask : 0x30, but need to check for buffer related
  43. // descriptors first )
  44. CopyHandle = 0x00,
  45. MoveHandle = 0x10,
  46. CallingPid = 0x20,
  47. };
  48. union Header {
  49. u32 raw;
  50. BitField<0, 6, u32> translate_params_size;
  51. BitField<6, 6, u32> normal_params_size;
  52. BitField<16, 16, u32> command_id;
  53. };
  54. /**
  55. * @brief Creates a command header to be used for IPC
  56. * @param command_id ID of the command to create a header for.
  57. * @param normal_params_size Size of the normal parameters in words. Up to 63.
  58. * @param translate_params_size Size of the translate parameters in words. Up to 63.
  59. * @return The created IPC header.
  60. *
  61. * Normal parameters are sent directly to the process while the translate parameters might go
  62. * through modifications and checks by the kernel.
  63. * The translate parameters are described by headers generated with the IPC::*Desc functions.
  64. *
  65. * @note While @p normal_params_size is equivalent to the number of normal parameters,
  66. * @p translate_params_size includes the size occupied by the translate parameters headers.
  67. */
  68. inline u32 MakeHeader(u16 command_id, unsigned int normal_params_size,
  69. unsigned int translate_params_size) {
  70. Header header{};
  71. header.command_id.Assign(command_id);
  72. header.normal_params_size.Assign(normal_params_size);
  73. header.translate_params_size.Assign(translate_params_size);
  74. return header.raw;
  75. }
  76. constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
  77. return MoveHandle | ((num_handles - 1) << 26);
  78. }
  79. constexpr u32 CopyHandleDesc(u32 num_handles = 1) {
  80. return CopyHandle | ((num_handles - 1) << 26);
  81. }
  82. constexpr u32 CallingPidDesc() {
  83. return CallingPid;
  84. }
  85. constexpr bool IsHandleDescriptor(u32 descriptor) {
  86. return (descriptor & 0xF) == 0x0;
  87. }
  88. constexpr u32 HandleNumberFromDesc(u32 handle_descriptor) {
  89. return (handle_descriptor >> 26) + 1;
  90. }
  91. union StaticBufferDescInfo {
  92. u32 raw;
  93. BitField<0, 4, u32> descriptor_type;
  94. BitField<10, 4, u32> buffer_id;
  95. BitField<14, 18, u32> size;
  96. };
  97. inline u32 StaticBufferDesc(u32 size, u8 buffer_id) {
  98. StaticBufferDescInfo info{};
  99. info.descriptor_type.Assign(StaticBuffer);
  100. info.buffer_id.Assign(buffer_id);
  101. info.size.Assign(size);
  102. return info.raw;
  103. }
  104. /**
  105. * @brief Creates a header describing a buffer to be sent over PXI.
  106. * @param size Size of the buffer. Max 0x00FFFFFF.
  107. * @param buffer_id The Id of the buffer. Max 0xF.
  108. * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
  109. * read-write access.
  110. * @return The created PXI buffer header.
  111. *
  112. * The next value is a phys-address of a table located in the BASE memregion.
  113. */
  114. inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
  115. u32 type = PXIBuffer;
  116. if (is_read_only)
  117. type |= 0x2;
  118. return type | (size << 8) | ((buffer_id & 0xF) << 4);
  119. }
  120. enum MappedBufferPermissions : u32 {
  121. R = 1,
  122. W = 2,
  123. RW = R | W,
  124. };
  125. union MappedBufferDescInfo {
  126. u32 raw;
  127. BitField<0, 4, u32> flags;
  128. BitField<1, 2, MappedBufferPermissions> perms;
  129. BitField<4, 28, u32> size;
  130. };
  131. inline u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
  132. MappedBufferDescInfo info{};
  133. info.flags.Assign(MappedBuffer);
  134. info.perms.Assign(perms);
  135. info.size.Assign(size);
  136. return info.raw;
  137. }
  138. inline DescriptorType GetDescriptorType(u32 descriptor) {
  139. // Note: Those checks must be done in this order
  140. if (IsHandleDescriptor(descriptor))
  141. return (DescriptorType)(descriptor & 0x30);
  142. // handle the fact that the following descriptors can have rights
  143. if (descriptor & MappedBuffer)
  144. return MappedBuffer;
  145. if (descriptor & PXIBuffer)
  146. return PXIBuffer;
  147. return StaticBuffer;
  148. }
  149. } // namespace IPC