NameDateSize

..25-Sep-202022

CMakeLists.txtH A D25-Jul-20191.2 KiB

include/H25-Jul-20193

LICENSE_BSD2.txtH A D25-Jul-20191.4 KiB

README.mdH A D04-Nov-202011.7 KiB

src/H25-Jul-20197

README.md

1<!---
2  Copyright 2017, Data61
3  Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4  ABN 41 687 119 230.
5
6  This software may be distributed and modified according to the terms of
7  the BSD 2-Clause license. Note that NO WARRANTY is provided.
8  See "LICENSE_BSD2.txt" for details.
9
10    @TAG(DATA61_BSD)
11-->
12# 1. MISSION STATEMENT AND CURRENT STATUS.
13
14The Serial Server thread is able to connect to a character device and act as a
15multiplexer for writes to that device.
16
17Generally the server's error messages are very descriptive, and you should be
18able to tell what went wrong if you triggered an error.
19
20## 1.1. CURRENT SUPPORTED FEATURES:
21* Binding to a platform serial device.
22* Writing to the platform serial device.
23* Serializing access to the serial device from multiple clients.
24
25## 1.2. CURRENTLY UNSUPPORTED FEATURES:
26* Reading from the platform serial device.
27* Multiple server instances.
28* Write-back buffering or any kind of cache-type buffering really.
29
30# 2. TOP LEVEL DESIGN
31
32> **Caution**:
33>
34> All `vka_t`, `vspace_t` and `simple_t` instances provided to this library
35> must remain functional for the duration of the Server thread's lifetime.
36
37## 2.1. ROLES.
38
39The library works on the basis of 3 roles being played by 3 parties:
40
41* The "Parent", which spawns the server thread by calling
42`serial_server_parent_spawn_thread()`. It is also generally, though not necessarily,
43going to be the job of the Parent, to provide CSpace slots for the
44Server to mint badged caps to its Endpoint into, but this may be done by any other
45thread that exists in the same VSpace as the Server (because the Server's
46badge-value allocation metadata exists in the Server's VSpace).
47* The "Server", which is spawned by the Parent, and multiplexes accesses to the
48underlying serial device. The Server also provides a badge value allocator that
49the Parent *must* use when it is minting the Endpoint capabilities to the Clients.
50* The "Clients", which connect to the Server and print through it. The Clients
51need to have an endpoint minted to them by the Parent, or else they need to
52somehow acquire a badged capability to the Server's Endpoint, the badge of which
53was generated by the library.
54
55Finally, some party must spawn the client threads themselves; this party is,
56while a recognized actor, not a necessary part of the library specification.
57
58## 2.2. ROLE QUICK REFERENCE (TL;DR):
59
60Basic quick walkthrough of what you need to do, in order to get each role
61working. Written role-specific so you only need to read the section you care
62about.
63
64### 2.2.1. SERVER QUICK REFERENCE:
65
66You don't need to do anything with the server. If you want to know how to
67_spawn_ the server, that's the role of the Parent.
68
69### 2.2.2. PARENT QUICK REFERENCE:
70
71Header: `#include <sel4utils/serial_server/parent.h>`.
72
73Of the three roles, the Parent does the most work, and is responsible for:
74
75* Spawning the Server.
76* Generally, but not necessarily: allocating CSpace slots in the clients' CSpaces
77  into which the Server library will mint badged Endpoint capabilities.
78
79To spawn the Server, you'll need:
80
81* A `simple_t` instance that has information about the Parent.
82* A `vka_t` instance that manages the Parent's CSpace.
83* A `vspace_t` instance that manages the Parent's VSpace.
84
85When you have all of those, go ahead and spawn the Server thread like this:
86    int error;
87
88    error = serial_server_parent_spawn_thread(...);
89    if (error != 0) {
90        ZF_LOGF("Failed to spawn the server with error %d.", error);
91    }
92    ZF_LOGF("Serial server spawned.");
93
94> #### Behaviour / Side effects
95>
96> * The server works with the assumption that it will be spawned in the Parent's
97>   VSpace and CSpace, and it expects to be given the Parent's vspace_t, vka_t
98>   and simple_t.
99> * When the Server thread is spawned, the library automatically creates an
100>   Endpoint object that it will listen on, and stores it a capability to this
101>   Endpoint internally.
102> * Keep all vka_t, vspace_t and simple_t instances that are passed to this
103>   library alive for the duration of the lifetime of the Server thread.
104
105Next you'll want to mint badged capabilities to the Server's Endpoint object,
106to all the Clients you intend to spawn. The library takes care of this in a
107two-fold manner:
108
109* It provides convenience functions for minting new, badged copies of the Server
110thread's Endpoint cap.
111* It keeps an internal badge value allocator, which the aforementioned
112convenience functions use to generate unique badge values for clients.
113
114The library provides several convenience functions that will help you mint these easily:
115
116* `serial_server_parent_vka_mint_endpoint(vka_t client_vka, cspacepath_t *result)`:
117This function will ALLOCATE and mint a new, badged copy of the Server's Endpoint and return
118the path into for it in `result`. Make sure you pass the **CLIENT**'s vka, and
119not the Server's vka, since you're trying to mint the new cap to the client.
120* `serial_server_allocate_client_badged_ep(cspacepath_t dest_path)`:
121This function will mint a new, badged copy of the Server's Endpoint into the
122designated slot -- this is meant to be used when the caller has already pre-allocated
123a slot that s/he would like the server to use.
124* `serial_server_parent_mint_endpoint_to_process(sel4utils_process_t *p)`:
125This function relies on `sel4utils_mint_cap_to_process()`, but basically fills out
126the arguments for you. By implication, it also takes up a slot in the destination
127process's CSpace, so **if you had some policy for your client threads' slots,
128you need to factor this function call into that policy**.
129
130In this quick-reference, we'll use `serial_server_parent_vka_mint_endpoint()`
131since it's super-convenient. We will be using 3 Client threads in our example:
132
133    #define SERSERV_README_N_CLIENTS (3)
134
135    vka_t client_vkas[SERSERV_README_N_CLIENTS];
136    cspacepath_t client_server_ep_cspaths[SERSERV_README_N_CLIENTS];
137
138    for (int i = 0; i < SERSERV_README_N_CLIENTS; i++) {
139        /* I'm not going to cover how to initialize vkas here. */
140        SETUP_YOUR_CLIENT'S_VKA(&client_vkas[i]);
141
142        /* Ask the Server to Mint badged endpoints to the clients: the library
143         * automatically both allocates a unique badge value and mints the
144         * capability for us.
145         *
146         * We chose here to use `serial_server_parent_vka_mint_endpoint()`, but
147         * the other functions provided by the library would have worked fine.
148         */
149        error = serial_server_parent_vka_mint_endpoint(&client_vkas[i],
150                                                       &client_server_ep_cspaths[i]);
151    }
152
153    /* At the end of this loop, each Client has a badged capability to the
154     * Endpoint that the server is listening on. (The client processes/threads
155     * have not been spawned yet.)
156     *
157     * You want to keep the CPtrs to the badged endpoints somewhere safe,
158     * because you'll need them later.
159     */
160
161Make sure that you save the CPtrs to the badged Endpoints that the library
162returned to you: you'll need them later on. If your new Client will live in
163a new VSpace or CSpace, **make sure you plan for how to make the these caps
164visible to them**.
165
166Finally, either the Parent or some other actor will have to actually spawn the
167clients. I won't be covering how to spawn TCBs/CSpaces/VSpaces, etc here, but
168it'll look something like:
169
170    for (int i = 0; i < SERSERV_README_N_CLIENTS; i++) {
171        MAKE_SERVER's_BADGED_ENDPOINT_CAPABILITY_VISIBLE_TO_CLIENT(i);
172
173        SPAWN_CLIENT_THREAD_OR_PROCESS(i);
174    }
175
176### 2.2.3. CLIENT QUICK REFERENCE:
177
178Header: `#include <sel4utils/serial_server/client.h>`.
179
180The Client role is extremely simple: you retrieve the badged Endpoint capability
181that was minted for you by the Parent, and then you call
182`serial_server_client_connect()` to connect to the server. From then on, you can
183call `serial_server_printf()` to ask the server to print.
184
185A call to `serial_server_client_connect()` requires:
186
187* The client's badged Server endpoint capability.
188* An initialized vka_t instance which is able to allocate resources on behalf
189  of the client. If the client lives in the same CSpace as the Parent, this will
190  be the Parent's VKA.
191* An initialize vspace_t instance which is able to allocate memory on behalf of
192  the client. If the client lives in the same VSpace as the Parent, this will
193  be the Parent's VSpace.
194* An uninitialized `serial_client_context_t`, which is your context-cookie
195  to the server.
196
197You can use the library from a client like this:
198
199    void client_main(void)
200    {
201        seL4_CPtr my_server_ep_cap;
202        vka_t *my_vka;
203        vspace_t *my_vspace;
204        serial_client_context_t my_conn;
205        int error;
206
207        RETRIEVE_MY_BADGED_EP_CAP(&my_server_ep_cap);
208
209        my_vka = OBTAIN_A_VKA_THAT_WORKS_FOR_MY_CSPACE();
210        my_vspace = OBTAIN_A_VSPACE_THAT_WORKS_FOR_MY_VSPACE();
211
212        error = serial_server_client_connect(my_server_ep_cap,
213                                             my_vka, my_vspace,
214                                             &my_conn);
215        if (error != 0) {
216            ZF_LOGF("Failed to connect to the server.");
217        }
218
219        /* From here on, you're free to print. */
220        serial_server_printf(&my_conn, "Hello world from %s.\n", "John Doe");
221    }
222
223> #### Behaviour / Side effects
224>
225> * `serial_server_client_connect()` establishes a shared-memory window
226> between the client and server. Make sure that you have enough virtual
227> memory in both VSpaces, and make sure you have enough physical memory.
228> At present, the shared mem window is 1 page in size.
229> * `serial_server_client_connect()` also sends capabilities to the server via
230> IPC. Be sure that the badged Endpoint capabilities generated for each
231> client have the **GRANT** right on them.
232
233# 3. HIGH LEVEL SERIAL SERVER MECHANICS:
234
235## 3.1 DISCONNECTING:
236
237Disconnecting causes the Server to tear down its connection to a specific
238Client. That client will thenceforth be ignored by the Server, just as if it had
239never connected in the first place. The client may subsequently reconnect if it
240so desires.
241
242> #### Behaviour / Side effects:
243>
244> After being disconnected, the only operation that a former Client can invoke
245> on the Server is the `serial_server_client_connect()` function.
246
247### 3.1.1: DISCONNECTING, SERVER ROLE AND PARENT ROLE:
248
249You don't need to do anything with the Server or Parent when you wish to
250disconnect a Client from the Server.
251
252### 3.1.2: DISCONNECTING, CLIENT ROLE:
253
254To disconnect a client from the Server, simply retrieve a pointer to your
255connection token, and then call `serial_server_disconnect()`. (Your connection
256token was filled out and returned to you when you called
257`serial_server_client_connect()`).
258
259    void client_main(void)
260    {
261        serial_client_context_t conn;
262
263        serial_server_client_connect(&conn, ...);
264
265        /* ... */
266
267        serial_server_disconnect(&conn);
268    }
269
270That's it.
271
272## 3.2 KILLING THE SERVER:
273
274Killing the server causes the Server thread to first stop listening for
275requests (it exits its message loop), and then unilaterally tear down all
276connections to its current clients, before Suspending itself.
277
278This operation may only be performed by a current Client of the Server. If your
279Parent wishes to kill the Server, it itself will have to also connect to the
280Server.
281
282### 3.2.1 KILLING, SERVER ROLE AND PARENT ROLE:
283
284You don't need to do anything with the Server or Parent when you wish to kill the
285Server. If you wish to kill the Server from the Parent, then the Parent will
286also itself need to connect to the Server.
287
288### 3.2.2 KILLING, CLIENT ROLE:
289
290To kill the Server, simply obtain a handle to your connection token, and then
291call `serial_server_kill()`:
292
293    void client_main(void)
294    {
295        serial_client_context_t conn;
296
297        serial_server_client_connect(&conn);
298
299        /* ... */
300
301        serial_server_kill(&conn);
302    }
303