| 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 |  |