1/** 2 * \file 3 * \brief Legacy IDC buffer format. PLEASE DO NOT USE FOR ANY NEW CODE! 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#ifndef BARRELFISH_LEGACY_IDC_BUFFER_H 16#define BARRELFISH_LEGACY_IDC_BUFFER_H 17 18/** 19 * \brief Maximum total length of IDC message (header + payload) 20 * 21 * Determined by number of registers available to transfer messages. 22 */ 23// XXX Doesnt that sound ever so slightly machine dependent to you ??? 24// XXX See also related magic in syscalls.c 25#define IDC_SEND_LENGTH 12 26 27/// Length of IDC message headers 28// XXX Is there a good reason that this isnt just done with sizeof() ??? 29#if defined(__SIZEOF_POINTER__) 30#if __SIZEOF_POINTER__ == 4 31#define IDC_SEND_HEADER_LENGTH 3 32#elif __SIZEOF_POINTER__ == 8 33#define IDC_SEND_HEADER_LENGTH 2 34#else 35#error "Unknown pointer size" 36#endif 37#else 38#error "Unknown pointer size" 39#endif 40 41/// Length of IDC message payload 42#define IDC_MSG_LENGTH (IDC_SEND_LENGTH - IDC_SEND_HEADER_LENGTH) 43 44#include <assert.h> 45#include <string.h> 46#include <stdlib.h> // for abort 47 48#if __x86_64__ 49typedef unsigned int idc_flag_t; 50#elif __i386__ 51typedef unsigned int idc_flag_t; 52#elif __arm__ 53typedef uint8_t idc_flag_t; 54#else 55#error "Unknown architecture." 56#endif 57 58#ifdef IN_KERNEL 59#define idc_fatal_error(x, ...) panic(x, __VA_ARGS__) 60#else // IN_KERNEL 61#define idc_fatal_error(x, ...) abort(); 62#endif // IN_KERNEL 63 64/** 65 * \brief IDC sender-side header. 66 */ 67union idc_send_header { 68 uintptr_t raw[IDC_SEND_HEADER_LENGTH]; 69 struct { 70 struct __attribute__ ((__packed__)) { 71 idc_flag_t sync :1; ///< Synchronous call (yields caller's timeslice) 72 idc_flag_t yield :1; ///< Yield to receiver if disabled/unable to transfer 73 } flags; 74 uint8_t length; ///< Length of payload in words 75 uint8_t invoke_bits; ///< Valid bits in invoke_cptr 76 uint8_t send_bits; ///< Valid bits in send_cptr 77 capaddr_t invoke_cptr; ///< Cap to invoke 78 capaddr_t send_cptr; ///< Cap to send or #CPTR_NULL 79 } x; 80}; 81 82/** 83 * \brief IDC receiver-side header. 84 */ 85union idc_recv_header { 86 uintptr_t raw; 87 struct { 88 struct __attribute__ ((__packed__)) { 89 idc_flag_t captransfer :1; ///< A cap was transferred 90 } flags; 91 uint8_t length; ///< Length of payload in words 92 } x; 93}; 94 95/** 96 * \brief Message layout on sender side. 97 */ 98union idc_send_msg_body { 99 uintptr_t raw[IDC_SEND_LENGTH]; ///< Raw message contents 100 101 struct { 102 union idc_send_header header; 103 uintptr_t words[IDC_MSG_LENGTH]; ///< Message payload 104 } x; 105}; 106 107/** 108 * \brief Message layout on receiver side. 109 */ 110struct idc_recv_msg_body { 111 union idc_recv_header header; ///< Header 112 uintptr_t words[IDC_MSG_LENGTH]; ///< Message payload 113}; 114 115/// IDC send message, with position indicator for marshalling 116struct idc_send_msg { 117 int pos; ///< Index in message 118 union idc_send_msg_body u; ///< Actual transferred message content 119}; 120 121/// IDC receive message, with position indicator for demarshalling 122struct idc_recv_msg { 123 int pos; ///< Index in message 124 struct idc_recv_msg_body msg; ///< Actual transferred message content 125}; 126 127static inline uintptr_t *idc_get_raw(struct idc_send_msg *msg) 128{ 129 return msg->u.raw; 130} 131 132static inline errval_t idc_msg_decode_word(struct idc_recv_msg *msg, 133 uintptr_t *ret) 134{ 135 assert(ret != NULL); 136 if(msg->pos < msg->msg.header.x.length) { 137 *ret = msg->msg.words[msg->pos++]; 138 return SYS_ERR_OK; 139 } else { 140 return SYS_ERR_IDC_MSG_BOUNDS; 141 } 142} 143 144/** 145 * \brief decode a word from the message 146 * \returns the word, or 0 if out of bounds 147 * \bug XXX: do not use this for new code! 148 */ 149static inline uintptr_t idc_msg_decode_word_or_zero(struct idc_recv_msg *msg) 150{ 151 uintptr_t w; 152 if (err_is_ok(idc_msg_decode_word(msg, &w))) { 153 return w; 154 } else { 155 return 0; 156 } 157} 158 159static inline void idc_msg_encode_word(struct idc_send_msg *msg, uintptr_t word) 160{ 161 if(msg->pos < IDC_MSG_LENGTH) { 162 msg->u.x.words[msg->pos++] = word; 163 msg->u.x.header.x.length = msg->pos; 164 } 165 else { 166 idc_fatal_error("%s: msg %p pos %d", 167 __FUNCTION__, msg, (int)msg->pos); 168 } 169} 170 171static inline void idc_msg_init(struct idc_send_msg *msg) 172{ 173 int i; 174 msg->pos = 0; 175 for (i = 0; i < IDC_SEND_HEADER_LENGTH; i++) { 176 msg->u.raw[i] = 0; 177 } 178 179 // Sync, yielding IDC is the default 180 msg->u.x.header.x.flags.sync = 1; 181 msg->u.x.header.x.flags.yield = 1; 182} 183 184// Set the msg flag to be async 185static inline void idc_msg_set_async(struct idc_send_msg *msg) 186{ 187 msg->u.x.header.x.flags.sync = 0; 188} 189 190// Macro cleanup 191#undef idc_fatal_error 192 193#endif // BARRELFISH_LEGACY_IDC_BUFFER_H 194