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