/* * Copyright (c) 2015-2016 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * File: kern/mach_node_link.h * Author: Dean Reece * Date: 2016 * * This header provides definitions required by Mach Node Link (MNL) drivers. * MNL drivers pass messages between nodes within a host. * * The constructs available at the node link level are very basic: * Node IDs (mach_node_id_t) uniquely identify nodes within a host. * MNL Info (mnl_node_info) describe the static characteristics of a node. * MNL Names (mnl_name_t) uniquely identify abjects across all nodes. * MNL Messages (mnl_msg) are passed between nodes (kernels) within a host. */ #ifndef _KERN_MACH_NODE_LINK_H_ #define _KERN_MACH_NODE_LINK_H_ #if KERNEL_PRIVATE #include <sys/cdefs.h> __BEGIN_DECLS /*** Node Info Section ***/ typedef int mach_node_id_t; // Used to uniquely identify a node extern mach_node_id_t localnode_id; // This node's unique id. /* An mnl_node struct describes static characteristcs of a node. The link * driver requests this structure from the mach_node layer and fills out * the fields. All fields must be filled in (non-zero) before both rx and tx * links are brought up. */ typedef struct mnl_node_info { mach_node_id_t node_id; // The node ID of this node uint8_t datamodel; // 1==ILP32, 2==LP64 (matches dtrace) uint8_t byteorder; // See libkern/OSByteOrder.h uint32_t proto_vers_min; // Oldest MNL protocol vers node can accept uint32_t proto_vers_max; // Newest MNL protocol vers node can accept } __attribute__ ((aligned (8))) *mnl_node_info_t; #define MNL_NODE_NULL ((mnl_node_info_t) 0UL) #define MNL_NODE_VALID(n) ((n) != MNL_NODE_NULL) #define MNL_PROTOCOL_V1 (1UL) // Current Node Link Protocol Version /*** Mach Node Link Name Section * * A node link name (mnl_name_t) is an oqaque value guaranteed unique across * kernel instances on all nodes. */ typedef uint64_t mnl_name_t; /*** Mach Node Link Message Section ***/ /* This structure is the header for an MNL Message buffer; the actual buffer * is normally larger, and holds this header followed by the body of the * message to be transmitted over the link. * * Note: The <node_id> and <size> fields are in host-native byte order when * passed to mnl_msg_from_node() and from mnl_msg_to_node(). * The byte order of these fields as sent over the link is left to the link * specification. The link drivers on both sides must translate these fields * between the link's byte order and host-native byte order. * * The body of the message, however, is treated as a byte-stream and passed * to/from the mach_node layer without any introspection or byte reordering. */ typedef struct mnl_msg { uint8_t sub; // 8b subsystem code uint8_t cmd; // 8b command code uint8_t qos; // 8b TODO: Doesn't do anything yet uint8_t flags; // 8b Command-specific flag byte uint32_t node_id; // 32b id of node that originated message mnl_name_t object; // 64b object ref (use is determined by sub & cmd) uint32_t options; // 32b Currently unused uint32_t size; // 32b Number of bytes that follow mnl_msg header } __attribute__((__packed__)) *mnl_msg_t; /* Allocate a mnl_msg struct plus additional payload. Link drivers are not * required to use this to allocate messages; any wired and mapped kernel * memory is acceptable. * * Arguments: * payload Number of additional bytes to allocate for message payload * flags Currently unused; 0 should be passed * * Return values: * MNL_MSG_NULL: Allocation failed * *: Pointer to new mnl_msg struct of requested size */ mnl_msg_t mnl_msg_alloc(int payload, uint32_t flags); /* Free a mnl_msg struct allocated by mnl_msg_alloc(). * * Arguments: * msg Pointer to the message buffer to be freed * flags Currently unused; 0 should be passed */ void mnl_msg_free(mnl_msg_t msg, uint32_t flags); #define MNL_MSG_NULL ((mnl_msg_t) 0UL) #define MNL_MSG_VALID(msg) ((msg) != MNL_MSG_NULL) #define MNL_MSG_SIZE ((vm_offset_t)sizeof(struct mnl_msg)) #define MNL_MSG_PAYLOAD(msg) ((vm_offset_t)(msg) + MNL_MSG_SIZE) /*** Mach Node Link Driver Interface Section ***/ /* The link driver calls this to setup a new (or restarted) node, and to get * an mnl_node_info struct for use as a parameter to other mnl functions. * If MNL_NODE_NULL is returned, the operation failed. Otherwise, a pointer * to a new mnl_node struct is returned. The caller should set all fields * in the structure, then call mnl_register() to complete node registration. * * Arguments: * nid The id of the node to be instantiated * flags Currently unused; 0 should be passed * * Return values: * MNL_NODE_NULL: Operation failed * *: Pointer to a new mnl_node struct */ mnl_node_info_t mnl_instantiate(mach_node_id_t nid, uint32_t flags); /* The link driver calls mnl_register() to complete the node registration * process. KERN_SUCCESS is returned if registration succeeded, otherwise * an error is returned. * * Arguments: * node Pointer to the node's mnl_node structure * flags Currently unused; 0 should be passed * * Return values: * KERN_SUCCESS: Registration succeeded * KERN_INVALID_ARGUMENT: Field(s) in <node> contained unacceptable values * KERN_*: Values returned from underlying functions */ kern_return_t mnl_register(mnl_node_info_t node, uint32_t flags); /* The link driver calls this to report that the link has been raised in one * or both directions. If the link is two uni-directional channels, each link * driver will independently call this function, each only raising the link * they are responsible for. The mach_node layer will not communicate with * the remote node until both rx and tx links are up. * * Arguments: * node Pointer to the node's mnl_node structure * link Indicates which link(s) are up (see MNL_LINK_* defines) * flags Currently unused; 0 should be passed * * Return values: * KERN_SUCCESS: Link state changed successfully. * KERN_INVALID_ARGUMENT: An argument value was not allowed. * KERN_*: Values returned from underlying functions. */ kern_return_t mnl_set_link_state(mnl_node_info_t node, int link, uint32_t flags); #define MNL_LINK_DOWN (0UL) #define MNL_LINK_RX (1UL) #define MNL_LINK_TX (2UL) #define MNL_LINK_UP (MNL_LINK_RX|MNL_LINK_TX) /* The link driver calls this to indicate a node has terminated and is no * longer available for messaging. This may be due to a crash or an orderly * shutdown, but either way the remote node no longer retains any state about * the remaining nodes. References held on behalf of the terminated node * will be cleaned up. After this is called, both the rx and tx links are * marked as down. If the remote node restarts, the link driver can bring * up the link using mnl_instantiate() again. * * Arguments: * node Pointer to the node's mnl_node structure * flags Currently unused; 0 should be passed * * Return values: * KERN_SUCCESS: Node was terminated. * KERN_INVALID_ARGUMENT: Node id was invalid or non-existant. * KERN_*: Values returned from underlying functions. */ kern_return_t mnl_terminate(mnl_node_info_t node, uint32_t flags); /* The link driver calls this to deliver an incoming message. Note that the * link driver must dispose of the memory pointed to by <msg> after the * function call returns. * * Arguments: * node Pointer to the node's mnl_node structure * msg Pointer to the message buffer * flags Currently unused; 0 should be passed */ void mnl_msg_from_node(mnl_node_info_t node, mnl_msg_t msg, uint32_t flags); /* The link driver calls this to fetch the next message to transmit. * This function will block until a message is available, or will return * FLIPC_MSG_NULL if the link is to be terminated. After the caller has * completed the transmission and no longer needs the msg buffer, it should * call mnl_msg_complete(). * * Arguments: * node Pointer to the node's mnl_node structure * flags Currently unused; 0 should be passed */ mnl_msg_t mnl_msg_to_node(mnl_node_info_t node, uint32_t flags); /* The link driver calls this to indicate that the specified msg buffer has * been sent over the link and can be deallocated. * * Arguments: * node Pointer to the node's mnl_node structure * msg Pointer to the message buffer * flags Currently unused; 0 should be passed */ void mnl_msg_complete(mnl_node_info_t node, mnl_msg_t msg, uint32_t flags); __END_DECLS #endif /* KERNEL_PRIVATE */ #endif /* _KERN_MACH_NODE_LINK_H_ */