| 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) | 
| 51 | typedef struct mach_node_server_msg { | 
| 52 | 	mach_msg_header_t   ; | 
| 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 |  */ | 
| 62 | typedef struct mach_node_server_register_msg { | 
| 63 | 	struct mach_node_server_msg ; | 
| 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 |  | 
| 94 | typedef 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 |  */ | 
| 103 | typedef struct mach_node *mach_node_t; | 
| 104 |  | 
| 105 | struct 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 |  | 
| 130 | extern 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 |  */ | 
| 153 | mach_node_t | 
| 154 | mach_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 |  */ | 
| 174 | extern mnl_name_t   mnl_name_alloc(void); | 
| 175 |  | 
| 176 | /*  Deallocate a unique name that was allocated via mnl_name_alloc(). | 
| 177 |  */ | 
| 178 | extern 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 |  */ | 
| 192 | typedef 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 |  */ | 
| 205 | void 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 |  */ | 
| 210 | mnl_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 |  */ | 
| 217 | mnl_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 |  */ | 
| 224 | kern_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 |  */ | 
| 252 | void 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 |  |