/ duct-tape / xnu / osfmk / kern / mach_node.h
mach_node.h
  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   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   */
 62  typedef 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  
 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_