xref: /xnu-11215.41.3/osfmk/ipc/flipc.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1 /*
2  * Copyright (c) 2015-2020 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  *	File:	ipc/flipc.h
30  *	Author:	Dean Reece
31  *	Date:	2016
32  *
33  *	Definitions for fast local ipc (flipc).
34  */
35 
36 #ifndef _IPC_FLIPC_H_
37 #define _IPC_FLIPC_H_
38 
39 #if MACH_KERNEL_PRIVATE && MACH_FLIPC
40 
41 #include <kern/mach_node.h>
42 #include <ipc/ipc_kmsg.h>
43 #include <sys/cdefs.h>
44 
45 __BEGIN_DECLS
46 
47 
48 /*** FLIPC Port Declarations ***/
49 
50 /*  A FLIPC port (flipc_port_t) is a companion structure to ipc_port_t.
51  *  Any ipc_port object that is known to the flipc layer has one of these
52  *  structures to maintain the state of the port with respect to flipc.
53  *  When a port reverts to a purely local object (all rights for the port exist
54  *  on a single node) the flipc port companion structure will be de-allocated.
55  */
56 
57 typedef struct flipc_port {
58 	struct mnl_obj          obj;            // Necessary to be in mnl_name_table[]
59 	ipc_port_t          lport;  // The associated local ipc_port
60 	mach_node_t                     hostnode;       // Node holding the recieve right
61 	uint32_t            peek_count; // How many kmsgs in mq have been peeked
62 	uint32_t            state:3;// See FPORT_STATE_* defines below
63 } *flipc_port_t;
64 
65 #define FPORT_NULL                      ((flipc_port_t) 0UL)
66 #define FPORT_VALID(fport)      ((fport) != FPORT_NULL)
67 
68 #define FPORT_STATE_INIT            (0) // Port is being initialized
69 #define FPORT_STATE_PROXY           (1) // Principal is on another node
70 #define FPORT_STATE_PRINCIPAL       (2) // Principal is on this node
71 #define FPORT_STATE_PREPRINCIPAL    (3) // Principal moving to this node
72 #define FPORT_STATE_POSTPRINCIPAL   (4) // Principal moving to other node
73 #define FPORT_STATE_DEAD            (5) // Port is being destroyed
74 
75 
76 /*** FLIPC Node Managment Declarations (used by mach node layer) ***/
77 
78 extern mach_node_id_t   localnode_id;   // This node's FLIPC id.
79 
80 /*  flipc_node_prepare() is called by mach node layer when a remote node is
81  *  registered by a link driver.  This is the flipc layer's opportunity to
82  *  convert it to a flipc port and hook it into any appropriate structures.
83  *  Note that the node is not yet in the mach node table.  Returns KERN_SUCCESS
84  *  on success; otherwise node is not prepared and cannot be used.
85  */
86 kern_return_t flipc_node_prepare(mach_node_t node);
87 
88 /*  flipc_node_retire() is called by mach node layer when a remote node is
89  *  terminated by a link driver.  This is the flipc layer's opportunity to
90  *  convert it back to a local port and unhook it into any structures.
91  *  Returns KERN_SUCCESS on success.
92  */
93 kern_return_t flipc_node_retire(mach_node_t node);
94 
95 
96 /*** FLIPC Message Declarations (used by mach node layer) ***/
97 
98 /*	Definition for a flipc ack/nak message.  These messages are sent to the
99  *  originating node of a message to ack or nak the message.  Ack'd messages
100  *  are destroyed by the originating node (to avoid duplicate delivery).  Nak'd
101  *  messages are re-sent to the node specified in <resend_to> (used when a
102  *  receive right moves to a different node).  These messages are queued onto
103  *  the originating node's control_port and sent along with other ipc traffic.
104  */
105 
106 typedef struct flipc_ack_msg {
107 	struct mnl_msg  mnl;        // Flipc message starts with mnl message
108 	mach_node_id_t  resend_to;  // Node ID for resends (if NAK)
109 	uint8_t         msg_count;  // Number of msgs being ackd/nakd
110 }   __attribute__((__packed__)) * flipc_ack_msg_t;
111 
112 #define FLIPC_CMD_ID (0x43504952UL) // msgh_id "RIPC" for FLIPC msgs
113 #define FLIPC_CMD_IPCMESSAGE    (1) // IPC Msg: <node> is sender; <fname> is dest port
114 #define FLIPC_CMD_ACKMESSAGE    (2) // <fname> is port being ack'd
115 #define FLIPC_CMD_NAKMESSAGE    (3) // <fname> is port being nak'd
116 
117 
118 /*  The node layer calls flipc_msg_to_remote_node() to fetch the next message
119  *  for <to_node>.  This function will block until a message is available or the
120  *  node is terminated, in which case it returns MNL_MSG_NULL.
121  */
122 mnl_msg_t flipc_msg_to_remote_node(mach_node_t  to_node,
123     uint32_t     flags);
124 
125 /*  The node layer calls flipc_msg_to_remote_node() to post the next message
126  *  from <from_node>.  This function will block until a message is available
127  *  or the node is terminated, in which case it returns MNL_MSG_NULL.
128  */
129 void flipc_msg_from_node(mach_node_t    from_node,
130     mnl_msg_t      msg_arg,
131     uint32_t       flags);
132 
133 /*  The node layer calls flipc_msg_free() to dispose of sent messages that
134  *  originated in the FLIPC layer.
135  */
136 void flipc_msg_free(mnl_msg_t   msg,
137     uint32_t    flags);
138 
139 
140 /*** FLIPC Message Declarations (used by mach ipc subsystem) ***/
141 
142 /*	Ack a message sent by <mqueue> to <fport>.  A new kmsg is allocated and
143  *  filled in as an ack (or nak if <delivered> is false), then posted to the
144  *  node's contol port.  This will wake the link driver (if sleeping) and cause
145  *  the ack to be included with normal IPC traffic.
146  *
147  *  This function immediately returns if <fport> or <node> is invalid, so it
148  *  is safe & quick to call speculatively.
149  *
150  *	Called from mach ipc_mqueue.c when a flipc-originated message is consumed.
151  */
152 void flipc_msg_ack(mach_node_t  node,
153     ipc_mqueue_t mqueue,
154     boolean_t    delivered);
155 
156 
157 __END_DECLS
158 
159 #endif  // MACH_KERNEL_PRIVATE
160 #endif  // _IPC_FLIPC_H_
161