| <!-- |
| Copyright 2019, Data61 |
| Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| ABN 41 687 119 230. |
| |
| This software may be distributed and modified according to the terms of |
| the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| See "LICENSE_BSD2.txt" for details. |
| |
| @TAG(DATA61_BSD) |
| --> |
| |
| # libsel4rpc |
| |
| Libsel4rpc provides a basic library for managing allocating resources over |
| process boundaries. It provides a protobuf-based protocol definition, and a few |
| simple wrappers to ease receiving/replying to RPC messages on the server side, |
| and sending RPC requests on the client side. |
| |
| Resource allocation across process boundaries is reasonably common in seL4, |
| where we often have a "parent" process (e.g. sel4test's driver), and a "child" |
| process (e.g. sel4test's tests). Previously, if the child process wanted a |
| resource (e.g. an IRQ, or a specific frame of memory), the parent had to know |
| in advance and supply the resource(s) to the parent process to the child at |
| process creation time. |
| |
| Libsel4rpc provides a simple way to remove the need for allocation in advance, |
| and allows the parent to provide capabilities to the child process on demand. |
| |
| For example, a small sample is below... |
| |
| Server: |
| ```c |
| // initialise the server |
| sel4rpc_server_env_t rpc_server; |
| sel4rpc_server_init(&rpc_server, vka, my_handler_function, my_data, |
| &env->reply, simple); |
| |
| // the main RPC loop |
| while (1) { |
| seL4_MessageInfo_t info = api_recv(process_ep, &badge, env->reply.cptr); |
| if (seL4_GetMR(0) == blah) { |
| sel4rpc_server_recv(&rpc_server); |
| } |
| } |
| ``` |
| |
| Client: |
| ```c |
| // initialise the client |
| sel4rpc_client_t rpc_client; |
| sel4rpc_client_init(&rpc_client, server_endpoint); |
| |
| // make an RPC request |
| // create the request object: allocate an untyped object at address 0x10440000 |
| // this will be encoded into the process's IPC buffer by sel4rpc_call |
| // and sent to the server. |
| RpcMessage msg = { |
| .which_msg = RpcMessage_memory_tag, |
| .msg.memory = { |
| .address = 0x10440000, |
| .size_bits = 12, |
| .type = seL4_UntypedObject, |
| }, |
| }; |
| |
| // set up somewhere to put our received capability |
| cspacepath_t path; |
| int ret = vka_alloc_path(vka, &path); |
| if (ret) |
| ZF_LOGF("Failed to alloc path: %d", ret); |
| |
| // call, putting the response cap (if there is one) into the cap |
| // represented by 'path'. |
| ret = sel4rpc_call(&rpc_client, &msg, path.root, path.capPtr, path.capDepth); |
| if (ret) |
| ZF_LOGF("RPC call failed: %d", ret); |
| |
| int errorCode = msg.msg.errorCode; |
| if (errorCode) |
| ZF_LOGF("RPC alloc request failed: %d", errorCode); |
| |
| // at this point, the cap was successfully allocated and is ready to use. |
| ``` |