1/*
2 * Copyright (c) 2015-2016 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: kern/mach_node.h
30 * Author: Dean Reece
31 * Date: 2016
32 *
33 * Definitions for mach internode communication (used by flipc).
34 * This header is intended for use inside the kernel only.
35 */
36
37#ifndef _KERN_MACH_NODE_H_
38#define _KERN_MACH_NODE_H_
39
40#if defined(MACH_KERNEL_PRIVATE) || defined(__APPLE_API_PRIVATE)
41
42/*** Mach Node Name Server Section
43 * Definitions shared by the mach_node layer in the kernel and the
44 * node's bootstrap server (noded).
45 */
46
47/* This structure describes messages sent from the mach_node layer to the
48 * node bootstrap server.
49 */
50#pragma pack(4)
51typedef struct mach_node_server_msg {
52 mach_msg_header_t header;
53 uint32_t identifier; // See FLIPC_SM_* defines
54 uint32_t options; // Currently unused
55 uint32_t node_id; // Node number
56} *mach_node_server_msg_t;
57#pragma pack()
58
59/* This structure describes node registration messages sent from the mach_node
60 * layer to the node bootstrap server.
61 */
62typedef struct mach_node_server_register_msg {
63 struct mach_node_server_msg node_header;
64 uint8_t datamodel; // 1==ILP32, 2==LP64; matches dtrace
65 uint8_t byteorder; // Uses defines from libkern/OSByteOrder.h
66} *mach_node_server_register_msg_t;
67#pragma pack()
68
69#define MACH_NODE_SERVER_MSG_ID (0x45444f4eUL) // msgh_id "NODE" for Node msgs
70#define MACH_NODE_SM_REG_LOCAL (0UL) // Register the local node
71#define MACH_NODE_SM_REG_REMOTE (1UL) // Register a remote node
72
73#if defined(__LP64__)
74#define LOCAL_DATA_MODEL (2) // Native data model is LP64
75#else
76#define LOCAL_DATA_MODEL (1) // Native data model is ILP32
77#endif
78
79#endif
80
81
82#if MACH_FLIPC && defined(MACH_KERNEL_PRIVATE)
83
84#include <kern/mach_node_link.h>
85#include <kern/queue.h>
86
87#include <sys/cdefs.h>
88
89__BEGIN_DECLS
90
91#define MACH_NODES_MAX (2) // Must be a power-of-2
92#define MACH_NODE_ID_VALID(nid) (((nid) >= 0) && ((nid) < MACH_NODES_MAX))
93
94typedef struct flipc_node *flipc_node_t; // Defined in ipc/flipc.h
95
96
97/*** Mach Node Section
98 *
99 * An instance of mach_node is allocated for each node known to mach.
100 * In-kernel interfaces use a pointer to this structure to refer to a node.
101 * External interfaces and protocols refer to node by id (mach_node_id_t).
102 */
103typedef struct mach_node *mach_node_t;
104
105struct mach_node {
106 /* Static node details, provided by the link driver at registration */
107 struct mnl_node_info info;
108
109 lck_spin_t node_lock_data;
110
111 /* Flags and status word */
112 uint32_t link:2; // See MNL_LINK* defines
113 uint32_t published:1; // True if node server has send-right
114 uint32_t active:1; // True if node is up and ready
115 uint32_t suspended:1; // True if node is active but sleeping
116 uint32_t dead:1; // True if node is dead
117 uint32_t _reserved:26; // Fill out the 32b flags field
118
119 /* port/space/set */
120 ipc_space_t proxy_space; // Kernel special space for proxy rights
121 ipc_pset_t proxy_port_set; // All proxy ports are in this set
122 ipc_port_t bootstrap_port; // Port for which "noded" holds rcv right
123 ipc_port_t control_port; // For control & ack/nak messages
124
125 /* Misc */
126 int proto_vers; // Protocol version in use for this node
127 mach_node_t antecedent; // Pointer to prior encarnation of this node id
128};
129
130extern mach_node_t localnode; // This node's mach_node_t struct
131
132#define MACH_NODE_NULL ((mach_node_t) 0UL)
133#define MACH_NODE_SIZE ((vm_offset_t)sizeof(struct mach_node))
134#define MACH_NODE_VALID(node) ((node) != MACH_NODE_NULL)
135#define MACH_NODE_ALLOC() ((mach_node_t)kalloc(MACH_NODE_SIZE))
136#define MACH_NODE_FREE(node) kfree(node, MACH_NODE_SIZE)
137
138#define MACH_NODE_LOCK_INIT(np) lck_spin_init(&(np)->node_lock_data, \
139 &ipc_lck_grp, &ipc_lck_attr)
140#define MACH_NODE_LOCK_DESTROY(np) lck_spin_destroy(&(np)->node_lock_data, \
141 &ipc_lck_grp)
142#define MACH_NODE_LOCK(np) lck_spin_lock(&(np)->node_lock_data)
143#define MACH_NODE_UNLOCK(np) lck_spin_unlock(&(np)->node_lock_data)
144
145/* Gets or allocates a locked mach_node struct for the specified <node_id>.
146 * The current node is locked and returned if it is not dead, or if it is dead
147 * and <alloc_if_dead> is false. A new node struct is allocated, locked and
148 * returned if the node is dead and <alloc_if_dead> is true, or if the node
149 * is absent and <alloc_if_absent> is true. MACH_NODE_NULL is returned if
150 * the node is absent and <alloc_if_absent> is false. MACH_NODE_NULL is also
151 * returned if a new node structure was not able to be allocated.
152 */
153mach_node_t
154mach_node_for_id_locked(mach_node_id_t node_id,
155 boolean_t alloc_if_dead,
156 boolean_t alloc_if_absent);
157
158
159/*** Mach Node Link Name Section
160 *
161 * A node link name (mnl_name_t) is an oqaque value guaranteed unique across
162 * kernel instances on all nodes. This guarantee requires that node ids not
163 * be recycled.
164 *
165 * Names 0..(MACH_NODES_MAX-1) represent null (invalid) names
166 * Names MACH_NODES_MAX..(MACH_NODES_MAX*2-1) represent bootstrap names
167 * Names >=(MACH_NODES_MAX*2) represent normal names.
168 */
169
170/* Allocate a new unique name and return it.
171 * Dispose of this with mnl_name_free().
172 * Returns MNL_NAME_NULL on failure.
173 */
174extern mnl_name_t mnl_name_alloc(void);
175
176/* Deallocate a unique name that was allocated via mnl_name_alloc().
177 */
178extern void mnl_name_free(mnl_name_t name);
179
180/* This macro is used to convert a node id to a bootstrap port name.
181 */
182#define MNL_NAME_BOOTSTRAP(nid) ((mnl_name_t) MACH_NODES_MAX | (nid))
183#define MNL_NAME_NULL ((mnl_name_t) 0UL)
184#define MNL_NAME_VALID(obj) ((obj) >= MACH_NODES_MAX)
185
186
187/* The mnl hash table may optionally be used by clients to associate mnl_names
188 * with objects. Objects to be stored in the hash table must start with an
189 * instance of struct mnk_obj. It is up to clients of the hash table to
190 * allocate and free the actual objects being stored.
191 */
192typedef struct mnl_obj {
193 queue_chain_t links; // List of mnk_name_obj (See kern/queue.h "Method 1")
194 mnl_name_t name; // Unique mnl_name
195} *mnl_obj_t;
196
197#define MNL_OBJ_NULL ((mnl_obj_t) 0UL)
198#define MNL_OBJ_VALID(obj) ((obj) != MNL_OBJ_NULL)
199
200
201/* Initialize the data structures in the mnl_obj structure at the head of the
202 * provided object. This should be called on an object before it is passed to
203 * any other mnl_obj* routine.
204 */
205void mnl_obj_init(mnl_obj_t obj);
206
207/* Search the local node's hash table for the object associated with a
208 * mnl_name_t and return it. Returns MNL_NAME_NULL on failure.
209 */
210mnl_obj_t mnl_obj_lookup(mnl_name_t name);
211
212/* Search the local node's hash table for the object associated with a
213 * mnl_name_t and remove it. The pointer to the removed object is returned so
214 * that the caller can appropriately dispose of the object.
215 * Returns MNL_NAME_NULL on failure.
216 */
217mnl_obj_t mnl_obj_remove(mnl_name_t name);
218
219/* Insert an object into the locak node's hash table. If the name of the
220 * provided object is MNL_NAME_NULL then a new mnl_name is allocated and
221 * assigned to the object. Returns KERN_SUCCESS, or KERN_NAME_EXISTS if
222 * an object associated with that name is already in the hash table.
223 */
224kern_return_t mnl_obj_insert(mnl_obj_t obj);
225
226
227/*** Mach Node Link Message Section ***
228 *
229 * Struct mnl_msg is only the header for a mnl_msg buffer;
230 * the actual buffer is normally larger. The rest of the buffer
231 * holds the body of the message to be transmitted over the link.
232 *
233 * Note: A mnl_msg received over a link will be in the byte-order of the
234 * node that send it. fname and size must be corrected to the hosts' native
235 * byte order by the link driver before it is sent up to the flipc layer.
236 * However, the link driver should not attempt to adjust the data model or
237 * byte order of the payload that follows the mnl_msg header - that will
238 * be done by the flipc layer.
239 */
240
241
242/* Values for mnl_msg.sub
243 */
244#define MACH_NODE_SUB_INVALID (0) // Never sent
245#define MACH_NODE_SUB_NODE (1) // MNL msg is for node management
246#define MACH_NODE_SUB_FLIPC (2) // MNL msg is for FLIPC subsystem
247#define MACH_NODE_SUB_VMSYS (3) // MNL msg is for VM subsystem
248
249
250/* Called whenever the node special port changes
251 */
252void mach_node_port_changed(void);
253
254
255__END_DECLS
256
257#endif // MACH_FLIPC && MACH_KERNEL_PRIVATE
258#endif // _KERN_MACH_NODE_H_
259
260