summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Subv2016-11-30 22:50:13 -0500
committerGravatar Subv2016-11-30 23:12:35 -0500
commit009b15b3aa9858930f461d825f7dd030fc963801 (patch)
tree060b6a82ad6c093b1832cd9e96a4fdacf29448b5 /src/core/hle/kernel
parentIPC/HLE: Associate the ClientSessions with their parent port's HLE interface ... (diff)
downloadyuzu-009b15b3aa9858930f461d825f7dd030fc963801.tar.gz
yuzu-009b15b3aa9858930f461d825f7dd030fc963801.tar.xz
yuzu-009b15b3aa9858930f461d825f7dd030fc963801.zip
A bit of a redesign.
Sessions and Ports are now detached from each other. HLE services are handled by means of a SessionRequestHandler class, Interface now inherits from this class. The File and Directory classes are no longer kernel objects, but SessionRequestHandlers instead, bound to a ServerSession when requested. File::OpenLinkFile now creates a new session pair and binds the File instance to it.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/client_port.cpp14
-rw-r--r--src/core/hle/kernel/client_port.h12
-rw-r--r--src/core/hle/kernel/client_session.cpp16
-rw-r--r--src/core/hle/kernel/client_session.h5
-rw-r--r--src/core/hle/kernel/server_session.cpp25
-rw-r--r--src/core/hle/kernel/server_session.h167
6 files changed, 24 insertions, 215 deletions
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 0ac36cd12..de67688c9 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -14,21 +14,7 @@ namespace Kernel {
14ClientPort::ClientPort() {} 14ClientPort::ClientPort() {}
15ClientPort::~ClientPort() {} 15ClientPort::~ClientPort() {}
16 16
17Kernel::SharedPtr<ClientPort> ClientPort::CreateForHLE(u32 max_sessions, std::shared_ptr<Service::Interface> hle_interface) {
18 SharedPtr<ClientPort> client_port(new ClientPort);
19 client_port->max_sessions = max_sessions;
20 client_port->active_sessions = 0;
21 client_port->name = hle_interface->GetPortName();
22 client_port->hle_interface = std::move(hle_interface);
23
24 return client_port;
25}
26
27void ClientPort::AddWaitingSession(SharedPtr<ServerSession> server_session) { 17void ClientPort::AddWaitingSession(SharedPtr<ServerSession> server_session) {
28 // A port that has an associated HLE interface doesn't have a server port.
29 if (hle_interface != nullptr)
30 return;
31
32 server_port->pending_sessions.push_back(server_session); 18 server_port->pending_sessions.push_back(server_session);
33 // Wake the threads waiting on the ServerPort 19 // Wake the threads waiting on the ServerPort
34 server_port->WakeupAllWaitingThreads(); 20 server_port->WakeupAllWaitingThreads();
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 52308f13f..7a53c93b8 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -23,14 +23,6 @@ public:
23 friend class ServerPort; 23 friend class ServerPort;
24 24
25 /** 25 /**
26 * Creates a serverless ClientPort that represents a bridge between the HLE implementation of a service/port and the emulated application.
27 * @param max_sessions Maximum number of sessions that this port is able to handle concurrently.
28 * @param hle_interface Interface object that implements the commands of the service.
29 * @returns ClientPort for the given HLE interface.
30 */
31 static Kernel::SharedPtr<ClientPort> CreateForHLE(u32 max_sessions, std::shared_ptr<Service::Interface> hle_interface);
32
33 /**
34 * Adds the specified server session to the queue of pending sessions of the associated ServerPort 26 * Adds the specified server session to the queue of pending sessions of the associated ServerPort
35 * @param server_session Server session to add to the queue 27 * @param server_session Server session to add to the queue
36 */ 28 */
@@ -44,12 +36,10 @@ public:
44 return HANDLE_TYPE; 36 return HANDLE_TYPE;
45 } 37 }
46 38
47 SharedPtr<ServerPort> server_port = nullptr; ///< ServerPort associated with this client port. 39 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
48 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 40 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
49 u32 active_sessions; ///< Number of currently open sessions to this port 41 u32 active_sessions; ///< Number of currently open sessions to this port
50 std::string name; ///< Name of client port (optional) 42 std::string name; ///< Name of client port (optional)
51 std::shared_ptr<Service::Interface> hle_interface = nullptr; ///< HLE implementation of this port's request handler
52
53private: 43private:
54 ClientPort(); 44 ClientPort();
55 ~ClientPort() override; 45 ~ClientPort() override;
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
index 22fa2ff03..31ea8045a 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -15,29 +15,17 @@ namespace Kernel {
15ClientSession::ClientSession() {} 15ClientSession::ClientSession() {}
16ClientSession::~ClientSession() {} 16ClientSession::~ClientSession() {}
17 17
18ResultVal<SharedPtr<ClientSession>> ClientSession::Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name) { 18ResultVal<SharedPtr<ClientSession>> ClientSession::Create(SharedPtr<ServerSession> server_session, std::string name) {
19 SharedPtr<ClientSession> client_session(new ClientSession); 19 SharedPtr<ClientSession> client_session(new ClientSession);
20 20
21 client_session->name = std::move(name); 21 client_session->name = std::move(name);
22 client_session->server_session = server_session; 22 client_session->server_session = server_session;
23 client_session->client_port = client_port;
24 client_session->hle_helper = client_port->hle_interface;
25
26 return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); 23 return MakeResult<SharedPtr<ClientSession>>(std::move(client_session));
27} 24}
28 25
29ResultCode ClientSession::HandleSyncRequest() { 26ResultCode ClientSession::HandleSyncRequest() {
30 // Signal the server session that new data is available 27 // Signal the server session that new data is available
31 ResultCode result = server_session->HandleSyncRequest(); 28 return server_session->HandleSyncRequest();
32
33 if (result.IsError())
34 return result;
35
36 // If this ClientSession has an associated HLE helper, forward the request to it.
37 if (hle_helper != nullptr)
38 result = hle_helper->HandleSyncRequest(server_session);
39
40 return result;
41} 29}
42 30
43} // namespace 31} // namespace
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index c2fc0d7dd..a951ea4d6 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -25,11 +25,10 @@ public:
25 /** 25 /**
26 * Creates a client session. 26 * Creates a client session.
27 * @param server_session The server session associated with this client session 27 * @param server_session The server session associated with this client session
28 * @param client_port The client port which this session is connected to
29 * @param name Optional name of client session 28 * @param name Optional name of client session
30 * @return The created client session 29 * @return The created client session
31 */ 30 */
32 static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name = "Unknown"); 31 static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, std::string name = "Unknown");
33 32
34 std::string GetTypeName() const override { return "ClientSession"; } 33 std::string GetTypeName() const override { return "ClientSession"; }
35 std::string GetName() const override { return name; } 34 std::string GetName() const override { return name; }
@@ -45,8 +44,6 @@ public:
45 44
46 std::string name; ///< Name of client port (optional) 45 std::string name; ///< Name of client port (optional)
47 SharedPtr<ServerSession> server_session; ///< The server session associated with this client session. 46 SharedPtr<ServerSession> server_session; ///< The server session associated with this client session.
48 SharedPtr<ClientPort> client_port; ///< The client port which this session is connected to.
49 std::shared_ptr<Service::Interface> hle_helper = nullptr; ///< HLE implementation of this port's request handler
50 47
51private: 48private:
52 ClientSession(); 49 ClientSession();
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 720c0eb94..200a7b815 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -14,11 +14,12 @@ namespace Kernel {
14ServerSession::ServerSession() {} 14ServerSession::ServerSession() {}
15ServerSession::~ServerSession() {} 15ServerSession::~ServerSession() {}
16 16
17ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { 17ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) {
18 SharedPtr<ServerSession> server_session(new ServerSession); 18 SharedPtr<ServerSession> server_session(new ServerSession);
19 19
20 server_session->name = std::move(name); 20 server_session->name = std::move(name);
21 server_session->signaled = false; 21 server_session->signaled = false;
22 server_session->hle_handler = hle_handler;
22 23
23 return MakeResult<SharedPtr<ServerSession>>(std::move(server_session)); 24 return MakeResult<SharedPtr<ServerSession>>(std::move(server_session));
24} 25}
@@ -34,23 +35,21 @@ void ServerSession::Acquire() {
34 35
35ResultCode ServerSession::HandleSyncRequest() { 36ResultCode ServerSession::HandleSyncRequest() {
36 // The ServerSession received a sync request, this means that there's new data available 37 // The ServerSession received a sync request, this means that there's new data available
37 // from one of its ClientSessions, so wake up any threads that may be waiting on a svcReplyAndReceive or similar. 38 // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or similar.
39
40 // If this ServerSession has an associated HLE handler, forward the request to it.
41 if (hle_handler != nullptr)
42 return hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
43
44 // If this ServerSession does not have an HLE implementation, just wake up the threads waiting on it.
38 signaled = true; 45 signaled = true;
39 WakeupAllWaitingThreads(); 46 WakeupAllWaitingThreads();
40 return RESULT_SUCCESS; 47 return RESULT_SUCCESS;
41} 48}
42 49
43SharedPtr<ClientSession> ServerSession::CreateClientSession() { 50std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) {
44 // In Citra, some types of ServerSessions (File and Directory sessions) are not created as a pair of Server-Client sessions, 51 auto server_session = ServerSession::Create(name + "Server", hle_handler).MoveFrom();
45 // but are instead created as a single ServerSession, which then hands over a ClientSession on demand (When opening the File or Directory). 52 auto client_session = ClientSession::Create(server_session, name + "Client").MoveFrom();
46 // The real kernel (Or more specifically, the real FS service) does create the pair of Sessions at the same time (via svcCreateSession), and simply
47 // stores the ClientSession until it is needed.
48 return ClientSession::Create(SharedPtr<ServerSession>(this), nullptr, name + "Client").MoveFrom();
49}
50
51std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(SharedPtr<ClientPort> client_port, const std::string& name) {
52 auto server_session = ServerSession::Create(name + "Server").MoveFrom();
53 auto client_session = ClientSession::Create(server_session, client_port, name + "Client").MoveFrom();
54 53
55 return std::make_tuple(server_session, client_session); 54 return std::make_tuple(server_session, client_session);
56} 55}
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 510b0a150..86fe641c0 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -10,158 +10,11 @@
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
12#include "core/hle/result.h" 12#include "core/hle/result.h"
13#include "core/hle/service/service.h"
13#include "core/memory.h" 14#include "core/memory.h"
14 15
15namespace IPC {
16
17enum DescriptorType : u32 {
18 // Buffer related desciptors types (mask : 0x0F)
19 StaticBuffer = 0x02,
20 PXIBuffer = 0x04,
21 MappedBuffer = 0x08,
22 // Handle related descriptors types (mask : 0x30, but need to check for buffer related
23 // descriptors first )
24 CopyHandle = 0x00,
25 MoveHandle = 0x10,
26 CallingPid = 0x20,
27};
28
29/**
30 * @brief Creates a command header to be used for IPC
31 * @param command_id ID of the command to create a header for.
32 * @param normal_params Size of the normal parameters in words. Up to 63.
33 * @param translate_params_size Size of the translate parameters in words. Up to 63.
34 * @return The created IPC header.
35 *
36 * Normal parameters are sent directly to the process while the translate parameters might go
37 * through modifications and checks by the kernel.
38 * The translate parameters are described by headers generated with the IPC::*Desc functions.
39 *
40 * @note While #normal_params is equivalent to the number of normal parameters,
41 * #translate_params_size includes the size occupied by the translate parameters headers.
42 */
43constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params,
44 unsigned int translate_params_size) {
45 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) |
46 (u32(translate_params_size) & 0x3F);
47}
48
49union Header {
50 u32 raw;
51 BitField<0, 6, u32> translate_params_size;
52 BitField<6, 6, u32> normal_params;
53 BitField<16, 16, u32> command_id;
54};
55
56inline Header ParseHeader(u32 header) {
57 return {header};
58}
59
60constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
61 return MoveHandle | ((num_handles - 1) << 26);
62}
63
64constexpr u32 CopyHandleDesc(u32 num_handles = 1) {
65 return CopyHandle | ((num_handles - 1) << 26);
66}
67
68constexpr u32 CallingPidDesc() {
69 return CallingPid;
70}
71
72constexpr bool isHandleDescriptor(u32 descriptor) {
73 return (descriptor & 0xF) == 0x0;
74}
75
76constexpr u32 HandleNumberFromDesc(u32 handle_descriptor) {
77 return (handle_descriptor >> 26) + 1;
78}
79
80constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
81 return StaticBuffer | (size << 14) | ((buffer_id & 0xF) << 10);
82}
83
84union StaticBufferDescInfo {
85 u32 raw;
86 BitField<10, 4, u32> buffer_id;
87 BitField<14, 18, u32> size;
88};
89
90inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) {
91 return {desc};
92}
93
94/**
95 * @brief Creates a header describing a buffer to be sent over PXI.
96 * @param size Size of the buffer. Max 0x00FFFFFF.
97 * @param buffer_id The Id of the buffer. Max 0xF.
98 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
99 * read-write access.
100 * @return The created PXI buffer header.
101 *
102 * The next value is a phys-address of a table located in the BASE memregion.
103 */
104inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
105 u32 type = PXIBuffer;
106 if (is_read_only)
107 type |= 0x2;
108 return type | (size << 8) | ((buffer_id & 0xF) << 4);
109}
110
111enum MappedBufferPermissions {
112 R = 1,
113 W = 2,
114 RW = R | W,
115};
116
117constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
118 return MappedBuffer | (size << 4) | (u32(perms) << 1);
119}
120
121union MappedBufferDescInfo {
122 u32 raw;
123 BitField<4, 28, u32> size;
124 BitField<1, 2, MappedBufferPermissions> perms;
125};
126
127inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) {
128 return {desc};
129}
130
131inline DescriptorType GetDescriptorType(u32 descriptor) {
132 // Note: Those checks must be done in this order
133 if (isHandleDescriptor(descriptor))
134 return (DescriptorType)(descriptor & 0x30);
135
136 // handle the fact that the following descriptors can have rights
137 if (descriptor & MappedBuffer)
138 return MappedBuffer;
139
140 if (descriptor & PXIBuffer)
141 return PXIBuffer;
142
143 return StaticBuffer;
144}
145
146} // namespace IPC
147
148namespace Kernel { 16namespace Kernel {
149 17
150static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header
151
152/**
153 * Returns a pointer to the command buffer in the current thread's TLS
154 * TODO(Subv): This is not entirely correct, the command buffer should be copied from
155 * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to
156 * the service handler process' memory.
157 * @param offset Optional offset into command buffer
158 * @return Pointer to command buffer
159 */
160inline u32* GetCommandBuffer(const int offset = 0) {
161 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
162 offset);
163}
164
165class ClientSession; 18class ClientSession;
166class ClientPort; 19class ClientPort;
167 20
@@ -183,11 +36,13 @@ public:
183 ~ServerSession() override; 36 ~ServerSession() override;
184 37
185 /** 38 /**
186 * Creates a server session. 39 * Creates a server session. The server session can have an optional HLE handler,
187 * @param name Optional name of the server session 40 * which will be invoked to handle the IPC requests that this session receives.
41 * @param name Optional name of the server session.
42 * @param hle_handler Optional HLE handler for this server session.
188 * @return The created server session 43 * @return The created server session
189 */ 44 */
190 static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); 45 static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown", std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr);
191 46
192 std::string GetTypeName() const override { return "ServerSession"; } 47 std::string GetTypeName() const override { return "ServerSession"; }
193 48
@@ -196,17 +51,10 @@ public:
196 51
197 /** 52 /**
198 * Creates a pair of ServerSession and an associated ClientSession. 53 * Creates a pair of ServerSession and an associated ClientSession.
199 * @param client_port ClientPort to which the sessions are connected
200 * @param name Optional name of the ports 54 * @param name Optional name of the ports
201 * @return The created session tuple 55 * @return The created session tuple
202 */ 56 */
203 static std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> CreateSessionPair(SharedPtr<ClientPort> client_port, const std::string& name = "Unknown"); 57 static std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> CreateSessionPair(const std::string& name = "Unknown", std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr);
204
205 /**
206 * Creates a portless ClientSession and associates it with this ServerSession.
207 * @returns ClientSession The newly created ClientSession.
208 */
209 SharedPtr<ClientSession> CreateClientSession();
210 58
211 /** 59 /**
212 * Handle a sync request from the emulated application. 60 * Handle a sync request from the emulated application.
@@ -221,5 +69,6 @@ public:
221 69
222 std::string name; ///< The name of this session (optional) 70 std::string name; ///< The name of this session (optional)
223 bool signaled; ///< Whether there's new data available to this ServerSession 71 bool signaled; ///< Whether there's new data available to this ServerSession
72 std::shared_ptr<Service::SessionRequestHandler> hle_handler; ///< This session's HLE request handler (optional)
224}; 73};
225} 74}