bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH mig] x86_64: adapt MiG generated stubs to use mach_port_name_inli


From: Flavio Cruz
Subject: [PATCH mig] x86_64: adapt MiG generated stubs to use mach_port_name_inlined_t for inlined port rights.
Date: Fri, 24 Nov 2023 16:30:40 -0500

For i686, we just change the code to use mach_port_name_inlined_t when
defining the types. This is a no-op.

For x86_64, there's a few things that are different:
- In the server code, the server handler can get inlined ports and the
  array will be resized and cast as an array of mach_port_name_t. Output
  parameters have a similar treatment where the inlined array in the
  output is used as an array of mach_port_name_t but resized to look like
  a mach_port_name_inlined_t.
- In the user side, we follow the same approach. Input ports as arrays
  of mach_port_name_t are expanded into an array of mach_port_name_inlined_t.
  Output ports are then converted back into an array of
  mach_port_name_inlined_t so that they fit into the expected message
  format.

Essentially, regardless of whether port rights are inline or out of
line, user interfaces and server stubs always receive an array of port
rights, not mach_port_name_inlined_t. However, inlined port rights will
be exchanged using mach_port_name_inlined_t.
---
 cpu.sym   |   1 +
 global.c  |   4 +-
 parser.y  |   4 --
 routine.c |   6 +++
 server.c  | 155 +++++++++++++++++++++++++++++++++++++++++-------------
 type.c    |  36 ++++++++-----
 type.h    |   5 ++
 user.c    | 123 ++++++++++++++++++++++++++++++++-----------
 utils.c   |  28 +++++++---
 9 files changed, 271 insertions(+), 91 deletions(-)

diff --git a/cpu.sym b/cpu.sym
index bee12f0..1ac2fae 100644
--- a/cpu.sym
+++ b/cpu.sym
@@ -105,6 +105,7 @@ expr sizeof(float)                  sizeof_float
 expr sizeof(double)                    sizeof_double
 expr sizeof(uintptr_t)                 sizeof_uintptr_t
 expr sizeof(intptr_t)                  sizeof_intptr_t
+expr (sizeof(uintptr_t)*8)             sizeof_uintptr_t_in_bits
 expr sizeof(mach_msg_header_t)         sizeof_mach_msg_header_t
 expr sizeof(mach_msg_type_long_t)      sizeof_mach_msg_type_long_t
 expr sizeof(mach_msg_type_t)           sizeof_mach_msg_type_t
diff --git a/global.c b/global.c
index 0ef1dca..bac667c 100644
--- a/global.c
+++ b/global.c
@@ -65,8 +65,8 @@ string_t InternalHeaderFileName = strNULL;
 string_t UserFileName = strNULL;
 string_t ServerFileName = strNULL;
 
-size_t port_size = port_name_size;
-size_t port_size_in_bits = port_name_size_in_bits;
+size_t port_size = sizeof_uintptr_t;
+size_t port_size_in_bits = sizeof_uintptr_t_in_bits;
 size_t complex_alignof = desired_complex_alignof;
 
 void
diff --git a/parser.y b/parser.y
index cac3379..5a73af8 100644
--- a/parser.y
+++ b/parser.y
@@ -210,10 +210,6 @@ Subsystem          :       SubsystemStart SubsystemMods
               IsKernelUser ? ", KernelUser" : "",
               IsKernelServer ? ", KernelServer" : "");
     }
-    if (IsKernelUser || IsKernelServer) {
-        port_size = vm_offset_size;
-        port_size_in_bits = vm_offset_size_in_bits;
-    }
     init_type();
 }
                        ;
diff --git a/routine.c b/routine.c
index 3ae9298..8909f4d 100644
--- a/routine.c
+++ b/routine.c
@@ -517,6 +517,12 @@ rtAugmentArgKind(argument_t *arg)
     {
        arg->argKind = akAddFeature(arg->argKind, akbPointer);
     }
+    if (akCheck(arg->argKind, akbSendRcv) &&
+        IS_64BIT_ABI &&
+        it->itUserlandPort &&
+       akCheck(arg->argKind, akbIndefinite)) {
+       arg->argKind = akAddFeature(arg->argKind, akbPointer);
+    }
 }
 
 /* arg->argType may be NULL in this function */
diff --git a/server.c b/server.c
index 00ca3f2..b95e4d0 100644
--- a/server.c
+++ b/server.c
@@ -455,10 +455,27 @@ WriteTypeCheck(FILE *file, const argument_t *arg)
                    arg->argRequestPos, arg->argTTName,
                    arg->argLongForm ? "l" : "",
                    it->itNumber);
-       fprintf(file, "\t    (In%dP->%s.msgt%s_size != %d)))\n",
-               arg->argRequestPos, arg->argTTName,
-               arg->argLongForm ? "l" : "",
-               it->itSize);
+       if (IS_64BIT_ABI && it->itUserlandPort && arg->argLongForm) {
+           /* 64 bit inlined ports are 8 bytes long but we use 
mach_port_name_t when passing them out of line. */
+           fprintf(file, "\t    (In%dP->%s.msgtl_size != %d && 
In%dP->%s.msgtl_header.msgt_inline == TRUE) || \n",
+                   arg->argRequestPos,
+                   arg->argTTName,
+                   it->itSize,
+                   arg->argRequestPos,
+                   arg->argTTName);
+           fprintf(file, "\t    (In%dP->%s.msgtl_size != %d && 
In%dP->%s.msgtl_header.msgt_inline == FALSE)",
+                   arg->argRequestPos,
+                   arg->argTTName,
+                   port_name_size_in_bits,
+                   arg->argRequestPos,
+                   arg->argTTName);
+       } else {
+           fprintf(file, "\t    (In%dP->%s.msgt%s_size != %d)",
+                   arg->argRequestPos, arg->argTTName,
+                   arg->argLongForm ? "l" : "",
+                   it->itSize);
+       }
+       fprintf(file, "))\n");
     }
     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
     fprintf(file, "#endif\t/* TypeCheck */\n");
@@ -565,6 +582,7 @@ static const char *
 InArgMsgField(const argument_t *arg)
 {
     static char buffer[100];
+    const ipc_type_t *it = arg->argType;
 
     /*
      * Inside the kernel, the request and reply port fields
@@ -588,6 +606,9 @@ static void
 WriteExtractArgValue(FILE *file, const argument_t *arg)
 {
     const ipc_type_t *it = arg->argType;
+    const bool is_inlined_port = it->itUserlandPort && it->itInLine &&
+               akIdent(arg->argKind) != akeRequestPort && 
akIdent(arg->argKind) != akeReplyPort;
+    const char* arg_suffix = is_inlined_port ? ".name" : "";
     bool have_payload;
 
     if (arg->argMultiplier > 1)
@@ -618,17 +639,18 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
                fprintf(file, "\t%s = %s;",
                        arg->argVarName, InArgMsgField(arg));
            else
-               WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
+               WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)",
                              arg->argVarName, it->itInTrans,
-                             InArgMsgField(arg));
+                             InArgMsgField(arg), arg_suffix);
        } else {
-           WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
+           WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)",
                          arg->argVarName, it->itInTrans,
-                         InArgMsgField(arg));
+                         InArgMsgField(arg), arg_suffix);
        }
-    } else
-       WriteCopyType(file, it, "%s", "/* %s */ %s",
-                     arg->argVarName, InArgMsgField(arg));
+    } else {
+       WriteCopyType(file, it, "%s", "/* %s */ %s%s",
+                     arg->argVarName, InArgMsgField(arg), arg_suffix);
+    }
     fprintf(file, "\n");
 }
 
@@ -745,12 +767,34 @@ WriteExtractArg(FILE *file, const argument_t *arg)
 
     if (akCheckAll(arg->argKind, akbReturnSnd|akbPointer))
        WriteInitializePtr(file, arg);
+    if (akCheckAll(arg->argKind, akbSendRcv|akbPointer)) {
+       if (akCheck(arg->argKind, akbIndefinite)) {
+           fprintf(file, "\tif (In%dP->%s%s.msgt_inline) {\n",
+                   arg->argRequestPos, arg->argTTName, arg->argLongForm ? 
".msgtl_header" : "");
+           fprintf(file, "\t\t%sP = (mach_port_t *)%s;\n", arg->argVarName, 
InArgMsgField(arg));
+           fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+           fprintf(file, "\t\t/* Resizes the mach_port_name_inlined_t input 
array as an array of mach_port_name_t. */\n");
+           fprintf(file, "\t\tfor (i = 1; i < In%dP->%s.msgt%s_number; i++) 
{\n",
+                   arg->argRequestPos, arg->argTTName, arg->argLongForm ? "l" 
: "");
+           fprintf(file, "\t\t\t%sP[i] = %s[i].name;\n", arg->argVarName, 
InArgMsgField(arg));
+           fprintf(file, "\t\t}\n");
+           fprintf(file, "\t} else {\n");
+           fprintf(file, "\t\t%sP = %s%s;\n", arg->argVarName, 
InArgMsgField(arg), OOLPostfix);
+           fprintf(file, "\t}\n");
+       }
+       else
+           assert(false);
+    }
 }
 
 static void
 WriteServerCallArg(FILE *file, const argument_t *arg)
 {
     const ipc_type_t *it = arg->argType;
+    const bool is_inlined_port = it->itUserlandPort &&
+               akIdent(arg->argKind) != akeRequestPort && 
akIdent(arg->argKind) != akeReplyPort && it->itInLine;
+    const char* arg_suffix = is_inlined_port ? ".name" : "";
+
     bool NeedClose = false;
 
     if (IsKernelServer) {
@@ -792,10 +836,10 @@ WriteServerCallArg(FILE *file, const argument_t *arg)
                    OOLPostfix);
        }
        else
-           fprintf(file, "%s", InArgMsgField(arg));
+           fprintf(file, "%s%s", InArgMsgField(arg), arg_suffix);
     }
     else
-       fprintf(file, "OutP->%s", arg->argMsgField);
+       fprintf(file, "OutP->%s%s", arg->argMsgField, arg_suffix);
 
     if (NeedClose)
        fprintf(file, ")");
@@ -818,7 +862,7 @@ WriteDestroyArg(FILE *file, const argument_t *arg)
         */
        argument_t *count = arg->argCount;
        ipc_type_t *btype = it->itElement;
-       int     multiplier = btype->itTypeSize / btype->itNumber;
+       int     multiplier = it->itUserlandPort ? port_name_size : 
btype->itTypeSize / btype->itNumber;
 
        fprintf(file, "\tif (OutP->%s == KERN_SUCCESS)\n",
                arg->argRoutine->rtRetCode->argMsgField);
@@ -938,6 +982,8 @@ static void
 WritePackArgValue(FILE *file, const argument_t *arg)
 {
     const ipc_type_t *it = arg->argType;
+    const bool is_inlined_port = it->itUserlandPort && it->itInLine;
+    const char* arg_suffix = is_inlined_port ? ".name" : "";
 
     fprintf(file, "\n");
 
@@ -965,6 +1011,7 @@ WritePackArgValue(FILE *file, const argument_t *arg)
        else {
            argument_t *count = arg->argCount;
            ipc_type_t *btype = it->itElement;
+           const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
 
            /* Note btype->itNumber == count->argMultiplier */
 
@@ -988,26 +1035,41 @@ WritePackArgValue(FILE *file, const argument_t *arg)
                            arg->argTTName,
                            arg->argLongForm ? ".msgtl_header" : "",
                            arg->argDealloc->argVarName);
+               if (is_64bit_port) {
+                   /* We are passing the ports out of line, so they will 
always have the same size as a port name. */
+                   fprintf(file, "\t\tOutP->%s%s.msgt_size = %d;\n",
+                           arg->argTTName,
+                           arg->argLongForm ? ".msgtl_header" : "",
+                           port_name_size_in_bits);
+               }
                fprintf(file, "\t\tOutP->%s%s = %sP;\n",
-                       arg->argMsgField,
-                       OOLPostfix,
-                       arg->argVarName);
+                   arg->argMsgField,
+                   OOLPostfix,
+                   arg->argVarName);
                if (!arg->argRoutine->rtSimpleFixedReply)
                    fprintf(file, "\t\tmsgh_simple = FALSE;\n");
-               fprintf(file, "\t}\n\telse {\n\t");
+               fprintf(file, "\t}\n\telse {\n");
+           }
+           fprintf(file, "\t\tif (%s) {\n", count->argVarName);
+           if (it->itIndefinite) {
+               if (is_64bit_port) {
+                   fprintf(file, "\t\t\t/* Copy array of mach_port_name_t into 
mach_port_name_inlined_t. */\n");
+                   fprintf(file, "\t\t\tmach_msg_type_number_t i;\n");
+                   fprintf(file, "\t\t\tfor(i = 0; i < %s; i++) {\n", 
count->argVarName);
+                   fprintf(file, "\t\t\t\t/* Clear the whole message with 
zeros. */\n");
+                   fprintf(file, "\t\t\t\tOutP->%s[i].kernel_port_do_not_use = 
0;\n", arg->argMsgField);
+                   fprintf(file, "\t\t\t\tOutP->%s[i].name = %s[i];\n", 
arg->argMsgField, arg->argVarName);
+                   fprintf(file, "\t\t\t}\n");
+               } else {
+                   fprintf(file, "\t\t\tmemcpy(OutP->%s, %s, ",
+                               arg->argMsgField, arg->argVarName);
+                   if (btype->itTypeSize > 1)
+                       fprintf(file, "%d * ", btype->itTypeSize);
+                   fprintf(file, "%s);\n", count->argVarName);
+               }
            }
-           fprintf(file, "\tif (%s)\n", count->argVarName);
-           if (it->itIndefinite)
-               fprintf(file, "\t");
-           fprintf(file, "\t\tmemcpy(OutP->%s, %s, ",
-                   arg->argMsgField, arg->argVarName);
-           if (btype->itTypeSize > 1)
-               fprintf(file, "%d * ",
-                       btype->itTypeSize);
-           fprintf(file, "%s);\n",
-               count->argVarName);
-           if (it->itIndefinite)
-               fprintf(file, "\t}\n");
+           fprintf(file, "\t\t}\n");
+           fprintf(file, "\t}\n");
        }
     }
     else if (arg->argMultiplier > 1)
@@ -1015,12 +1077,12 @@ WritePackArgValue(FILE *file, const argument_t *arg)
                      arg->argMsgField,
                      arg->argMultiplier,
                      arg->argVarName);
-    else if (it->itOutTrans != strNULL)
-       WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)",
-                     arg->argMsgField, it->itOutTrans, arg->argVarName);
-    else
-       WriteCopyType(file, it, "OutP->%s", "/* %s */ %s",
-                     arg->argMsgField, arg->argVarName);
+    else if (it->itOutTrans != strNULL) {
+       WriteCopyType(file, it, "OutP->%s%s", "/* %s%s */ %s(%s)",
+                     arg->argMsgField, arg_suffix, it->itOutTrans, 
arg->argVarName);
+    } else
+       WriteCopyType(file, it, "OutP->%s%s", "/* %s%s */ %s",
+                     arg->argMsgField, arg_suffix, arg->argVarName);
 }
 
 static void
@@ -1198,6 +1260,8 @@ WritePackArg(FILE *file, const argument_t *arg)
            fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n",
                    arg->argCount->argMsgField, arg->argMsgField);
        } else if (it->itIndefinite) {
+           const bool is_64bit_port = IS_64BIT_ABI && it->itUserlandPort;
+
            /*
             * We know that array is in reply message.
             */
@@ -1216,12 +1280,31 @@ WritePackArg(FILE *file, const argument_t *arg)
                        arg->argTTName,
                        arg->argLongForm ? ".msgtl_header" : "",
                        arg->argDealloc->argVarName);
+           if (is_64bit_port) {
+               /* We are passing the ports out of line, so they will always 
have the same size as a port name. */
+               fprintf(file, "\t\tOutP->%s%s.msgt_size = %d;\n",
+                       arg->argTTName,
+                       arg->argLongForm ? ".msgtl_header" : "",
+                       port_name_size_in_bits);
+           }
            fprintf(file, "\t\tOutP->%s%s = %sP;\n",
                        arg->argMsgField,
                        OOLPostfix,
                        arg->argVarName);
            if (!arg->argRoutine->rtSimpleFixedReply)
                fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+           if (is_64bit_port) {
+               fprintf(file, "\t} else {\n");
+               fprintf(file, "\t\t/* Resize mach_port_name_t array into 
mach_port_name_inlined_t. */\n");
+               fprintf(file, "\t\t/* Work in reverse order to avoid overriding 
subsequent entries. */\n");
+               fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+               fprintf(file, "\t\tfor(i = %s; i > 0; i--) {\n", 
arg->argCount->argVarName);
+               fprintf(file, "\t\t\tmach_port_name_t tmp_port_name = %sP[i - 
1];\n", arg->argVarName);
+               fprintf(file, "\t\t\t/* Clear the whole message with zeros. 
*/\n");
+               fprintf(file, "\t\t\tOutP->%s[i - 1].kernel_port_do_not_use = 
0;\n", arg->argMsgField);
+               fprintf(file, "\t\t\tOutP->%s[i - 1].name = tmp_port_name;\n", 
arg->argMsgField, arg->argVarName);
+               fprintf(file, "\t\t}\n");
+           }
            fprintf(file, "\t}\n");
        }
     }
diff --git a/type.c b/type.c
index c46f8f8..aaa01f9 100644
--- a/type.c
+++ b/type.c
@@ -121,6 +121,7 @@ itAlloc(void)
        false,                  /* bool itString */
        false,                  /* bool itVarArray */
        false,                  /* bool itIndefinite */
+       false,                  /* bool itUserlandPort */
        false,                  /* bool itKernelPort */
        itNULL,                 /* ipc_type_t *itElement */
        strNULL,                /* identifier_t itUserType */
@@ -195,6 +196,15 @@ itCalculateSizeInfo(ipc_type_t *it)
        warn("sizeof(%s) == 0", it->itName);
 }
 
+static bool
+itIsPortType(ipc_type_t *it)
+{
+    return ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
+           (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
+       MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
+       MACH_MSG_TYPE_PORT_ANY(it->itOutName);
+}
+
 /*
  * Fill in default values for some fields used in code generation:
  *     itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
@@ -213,6 +223,10 @@ itCalculateNameInfo(ipc_type_t *it)
     if (it->itServerType == strNULL)
        it->itServerType = it->itName;
 
+    bool isPortType = itIsPortType(it);
+    bool isServerPort = isPortType && streql(it->itServerType, "mach_port_t");
+    bool isUserPort = isPortType && streql(it->itUserType, "mach_port_t");
+
     /*
      * KernelServer and KernelUser interfaces get special treatment here.
      * On the kernel side of the interface, ports are really internal
@@ -226,25 +240,23 @@ itCalculateNameInfo(ipc_type_t *it)
      * hand-conditionalizing on KERNEL_SERVER and KERNEL_USER.
      */
 
-    if (IsKernelServer &&
-       streql(it->itServerType, "mach_port_t") &&
-       (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
-         (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
-        MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
-        MACH_MSG_TYPE_PORT_ANY(it->itOutName))) {
+    if (IsKernelServer && isServerPort) {
        it->itServerType = "ipc_port_t";
         it->itKernelPort = true;
-    } else if (IsKernelUser &&
-       streql(it->itUserType, "mach_port_t") &&
-       (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
-         (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
-        MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
-        MACH_MSG_TYPE_PORT_ANY(it->itOutName))) {
+    } else if (IsKernelUser && isUserPort) {
        it->itUserType = "ipc_port_t";
         it->itKernelPort = true;
     } else
         it->itKernelPort = false;
 
+    /*
+     * In 64 bits, ports are inlined as 8 bytes even though mach_port_t or
+     * mach_port_name_t are always 4 bytes. We do this to avoid slow message
+     * resizing inside the gnumach by ensuring inlined port names in messages
+     * are always 8 bytes long.
+     */
+    it->itUserlandPort = isPortType && !IsKernelUser && !IsKernelServer;
+
     if (it->itTransType == strNULL)
        it->itTransType = it->itServerType;
 }
diff --git a/type.h b/type.h
index 1e4e49f..a34c978 100644
--- a/type.h
+++ b/type.h
@@ -133,6 +133,10 @@ typedef enum dealloc {
  * itKernelPort is used only on kernel interfaces and is set to true when
  * the initial type is mach_port_t, which in turn is actually translated to
  * internal port pointers (ipc_port_t).
+ *
+ * itUserlandPort indicates that the field represents a port right (represented
+ * as a port name) and thus will only be true for userland stubs. This is
+ * used to change how inlined port names in messages are generated.
  */
 
 typedef struct ipc_type
@@ -163,6 +167,7 @@ typedef struct ipc_type
     bool itString;
     bool itVarArray;
     bool itIndefinite;
+    bool itUserlandPort;
     bool itKernelPort;
 
     struct ipc_type *itElement;        /* may be NULL */
diff --git a/user.c b/user.c
index e044b4f..d98ab98 100644
--- a/user.c
+++ b/user.c
@@ -424,6 +424,7 @@ WritePackArgValue(FILE *file, const argument_t *arg)
            const argument_t *count = arg->argCount;
            const char *countRef = count->argByReferenceUser ? "*" :"";
            const ipc_type_t *btype = it->itElement;
+           const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
 
            /* Note btype->itNumber == count->argMultiplier */
 
@@ -434,6 +435,15 @@ WritePackArgValue(FILE *file, const argument_t *arg)
                fprintf(file, "\t\tInP->%s%s.msgt_inline = FALSE;\n",
                        arg->argTTName,
                        arg->argLongForm ? ".msgtl_header" : "");
+               if (is_64bit_port) {
+                       /* Update size of the type to be the same as a port 
name since
+                        * we are passing port names out of line. */
+                       fprintf(file, "\t\t/* We are passing mach_port_name_t 
out of line. */\n");
+                       fprintf(file, "\t\tInP->%s%s.msgt_size = %d;\n",
+                               arg->argTTName,
+                               arg->argLongForm ? ".msgtl_header" : "",
+                               port_name_size_in_bits);
+               }
                if (arg->argDeallocate == d_YES)
                    fprintf(file, "\t\tInP->%s%s.msgt_deallocate = TRUE;\n",
                            arg->argTTName,
@@ -456,22 +466,38 @@ WritePackArgValue(FILE *file, const argument_t *arg)
 
            fprintf(file, "\t}\n\telse if (%s%s) {\n", countRef, 
count->argVarName);
 
-           fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField,
-               ref, arg->argVarName);
-           if (btype->itTypeSize > 1)
-               fprintf(file, "%d * ", btype->itTypeSize);
-           fprintf(file, "%s%s);\n",
-               countRef, count->argVarName);
+           if (is_64bit_port) {
+                   /* When copying inlined ports, the 64bit ABI uses 8 bytes 
to store port names,
+                    * hence we cannot use memcpy directly.
+                    */
+                   fprintf(file, "\t\t/* Transform mach_port_name_t into 
mach_port_name_inlined_t. */\n");
+                   fprintf(file, "\t\tmach_port_name_inlined_t *inlined_%s = 
(mach_port_name_inlined_t *)InP->%s;\n",
+                                   arg->argMsgField, arg->argMsgField);
+                   fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+                   fprintf(file, "\t\tfor (i = 0; i < %s%s; i++) {\n", 
countRef, count->argVarName);
+                   fprintf(file, "\t\t\t/* Clear the whole message with zeros. 
*/\n");
+                   fprintf(file, "\t\t\tinlined_%s[i].kernel_port_do_not_use = 
0;\n",
+                                   arg->argMsgField);
+                   fprintf(file, "\t\t\tinlined_%s[i].name = (%s%s)[i];\n", 
arg->argMsgField, ref, arg->argMsgField);
+                   fprintf(file, "\t\t}\n");
+           } else {
+                   fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", 
arg->argMsgField, ref, arg->argVarName);
+                   if (btype->itTypeSize > 1)
+                           fprintf(file, "%d * ", btype->itTypeSize);
+                   fprintf(file, "%s%s);\n", countRef, count->argVarName);
+           }
            fprintf(file, "\t}\n");
        }
     }
-    else if (arg->argMultiplier > 1)
+    else if (arg->argMultiplier > 1) {
        WriteCopyType(file, it, "InP->%s", "/* %s */ %d * %s%s",
                      arg->argMsgField, arg->argMultiplier,
                      ref, arg->argVarName);
-    else
-       WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
-                     arg->argMsgField, ref, arg->argVarName);
+    } else {
+       bool is_inlined_port = it->itUserlandPort && it->itInLine;
+       WriteCopyType(file, it, "InP->%s%s", "/* %s%s */ %s%s",
+                     arg->argMsgField, is_inlined_port ? ".name" : "", ref, 
arg->argVarName);
+    }
     fprintf(file, "\n");
 }
 
@@ -804,10 +830,23 @@ WriteTypeCheck(FILE *file, const argument_t *arg)
                    arg->argTTName,
                    arg->argLongForm ? "l" : "",
                    it->itNumber);
-       fprintf(file, "\t    (OutP->%s.msgt%s_size != %d)))\n",
-               arg->argTTName,
-               arg->argLongForm ? "l" : "",
-               it->itSize);
+       if (IS_64BIT_ABI && it->itUserlandPort && arg->argLongForm) {
+           /* 64 bit inlined ports are 8 bytes long but we use 
mach_port_name_t when passing them out of line. */
+           fprintf(file, "\t    (OutP->%s.msgtl_size != %d && 
OutP->%s.msgtl_header.msgt_inline == TRUE) || \n",
+                   arg->argTTName,
+                   it->itSize,
+                   arg->argTTName);
+           fprintf(file, "\t    (OutP->%s.msgtl_size != %d && 
OutP->%s.msgtl_header.msgt_inline == FALSE)",
+                   arg->argTTName,
+                   port_name_size_in_bits,
+                   arg->argTTName);
+       } else {
+           fprintf(file, "\t    (OutP->%s.msgt%s_size != %d)",
+                   arg->argTTName,
+                   arg->argLongForm ? "l" : "",
+                   it->itSize);
+       }
+       fprintf(file, "))\n");
     }
     WriteMsgError(file, rt, "MIG_TYPE_ERROR");
     fprintf(file, "#endif\t/* TypeCheck */\n");
@@ -907,6 +946,31 @@ WriteCheckMsgSize(FILE *file, const argument_t *arg)
     fprintf(file, "\n");
 }
 
+static void
+WriteExtractArgValueThroughCopy(FILE *file, const argument_t *arg, const 
argument_t *count,
+       const ipc_type_t *btype, const char *ref, const bool is_64bit_port)
+{
+    if (is_64bit_port) {
+       /* When copying inlined ports, the 64bit ABI uses 8 bytes to store port 
names,
+        * hence we cannot use memcpy.
+        */
+       fprintf(file, "\t\t/* Transform mach_port_name_inlined_t into 
mach_port_name_t. */\n");
+       fprintf(file, "\t\tmach_port_name_inlined_t *inlined_%s = 
(mach_port_name_inlined_t *)OutP->%s;\n",
+               arg->argMsgField, arg->argMsgField);
+       fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+       fprintf(file, "\t\tfor (i = 0; i < OutP->%s; i++) {\n", 
count->argMsgField);
+       fprintf(file, "\t\t\t(%s%s)[i] = inlined_%s[i].name;\n",
+               ref, arg->argVarName, arg->argMsgField);
+       fprintf(file, "\t\t}\n");
+    } else {
+       fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+               arg->argMsgField);
+       if (btype->itTypeSize != btype->itNumber)
+           fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+       fprintf(file, "OutP->%s);\n", count->argMsgField);
+    }
+}
+
 /*************************************************************
  *  Write code to copy an argument from the reply message
  *  to the parameter. Called by WriteRoutine for each argument
@@ -944,11 +1008,12 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
            const argument_t *count = arg->argCount;
            const char *countRef = count->argByReferenceUser ? "*" : "";
            const ipc_type_t *btype = argType->itElement;
+           const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
 
            fprintf(file, "\tif (!OutP->%s%s.msgt_inline)\n",
                    arg->argTTName,
                    arg->argLongForm ? ".msgtl_header" : "");
-           fprintf(file, "\t    %s%s = OutP->%s%s;\n",
+           fprintf(file, "\t\t%s%s = OutP->%s%s;\n",
                    ref, arg->argVarName,
                    arg->argMsgField,
                    OOLPostfix);
@@ -956,24 +1021,18 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
            if (btype->itNumber > 1)
                fprintf(file, " / %d", btype->itNumber);
            fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
-           fprintf(file, "\t    %smig_allocate((vm_offset_t *)%s,\n\t\t",
+           fprintf(file, "\t\t%smig_allocate((vm_offset_t *)%s, ",
                    SubrPrefix, arg->argVarName);       /* no ref! */
-           if (btype->itTypeSize != btype->itNumber)
-               fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
-           fprintf(file, "OutP->%s);\n", count->argMsgField);
-           fprintf(file, "\t    memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
-                   arg->argMsgField);
-           if (btype->itTypeSize != btype->itNumber)
+           if (is_64bit_port)
+               fprintf(file, "%d * ", port_name_size);
+           else if (btype->itTypeSize != btype->itNumber)
                fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
            fprintf(file, "OutP->%s);\n", count->argMsgField);
+           WriteExtractArgValueThroughCopy(file, arg, count, btype, ref, 
is_64bit_port);
            fprintf(file, "\t}\n");
            fprintf(file, "\telse if (OutP->%s) {\n", count->argMsgField);
 
-           fprintf(file, "\t    memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
-                   arg->argMsgField);
-           if (btype->itTypeSize != btype->itNumber)
-               fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
-           fprintf(file, "OutP->%s);\n", count->argMsgField);
+           WriteExtractArgValueThroughCopy(file, arg, count, btype, ref, 
is_64bit_port);
            fprintf(file, "\t}\n");
        }
        else {
@@ -1025,15 +1084,17 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
            fprintf(file, "\t}\n");
        }
     }
-    else if (arg->argMultiplier > 1)
+    else if (arg->argMultiplier > 1) {
        WriteCopyType(file, argType,
                      "%s%s", "/* %s%s */ OutP->%s / %d",
                      ref, arg->argVarName, arg->argMsgField,
                      arg->argMultiplier);
-    else
+    } else {
+       bool is_inlined_port = argType->itUserlandPort && argType->itInLine;
        WriteCopyType(file, argType,
-                     "%s%s", "/* %s%s */ OutP->%s",
-                     ref, arg->argVarName, arg->argMsgField);
+                     "%s%s", "/* %s%s */ OutP->%s%s",
+                     ref, arg->argVarName, arg->argMsgField, is_inlined_port ? 
".name" : "");
+    }
     fprintf(file, "\n");
 }
 
diff --git a/utils.c b/utils.c
index ec0f2d1..0d69cb2 100644
--- a/utils.c
+++ b/utils.c
@@ -317,6 +317,9 @@ WriteFieldDeclPrim(FILE *file, const argument_t *arg,
     if (it->itInLine && it->itVarArray)
     {
        ipc_type_t *btype = it->itElement;
+       identifier_t original_type_name = (*tfunc)(btype);
+       identifier_t inlined_type_name = btype->itUserlandPort ?
+           "mach_port_name_inlined_t" : original_type_name;
 
        /*
         *      Build our own declaration for a varying array:
@@ -325,19 +328,27 @@ WriteFieldDeclPrim(FILE *file, const argument_t *arg,
         */
        fprintf(file, "\t\tunion {\n");
        fprintf(file, "\t\t\t%s %s[%d];\n",
-                       (*tfunc)(btype),
+                       inlined_type_name,
                        arg->argMsgField,
                        it->itNumber/btype->itNumber);
        fprintf(file, "\t\t\t%s%s *%s%s;\n",
                        tfunc == FetchUserType && UserVarConst(arg)
                                ? "const " : "",
-                       (*tfunc)(btype),
+                       original_type_name,
                        arg->argMsgField,
                        OOLPostfix);
        fprintf(file, "\t\t};");
     }
     else
-       fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField);
+    {
+        identifier_t original_type_name = (*tfunc)(it);
+        identifier_t final_type_name = it->itUserlandPort && it->itInLine ?
+           "mach_port_name_inlined_t" : original_type_name;
+
+        fprintf(file, "\t\t%s %s;",
+               final_type_name,
+                arg->argMsgField);
+    }
 
     if (it->itPadSize != 0)
        fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize);
@@ -366,7 +377,11 @@ WriteStaticLongDecl(FILE *file, const ipc_type_t *it,
         * so we fill mach_msg_type_long_t just like mach_msg_type_t.
         */
        fprintf(file, "\t\t\t.msgt_name =\t\t(unsigned char) %s,\n", msgt_name);
-       fprintf(file, "\t\t\t.msgt_size =\t\t%d,\n", it->itSize);
+       /* In case we are passing out of line ports, we always send as a 
contiguous array of port names
+        * rather than mach_port_name_inlined_t. */
+       const u_int true_size = (it->itUserlandPort && !it->itInLine && 
it->itNumber == 0) ?
+           port_name_size_in_bits : it->itSize;
+       fprintf(file, "\t\t\t.msgt_size =\t\t%d,\n", true_size);
        fprintf(file, "\t\t\t.msgt_number =\t\t%d,\n", it->itNumber);
     } else {
        fprintf(file, "\t\t\t.msgt_name =\t\t0,\n");
@@ -407,10 +422,11 @@ WriteStaticShortDecl(FILE *file, const ipc_type_t *it,
     fprintf(file, "\t};\n");
     if (it->itInLine && !it->itVarArray) {
         identifier_t type = is_server ? FetchServerType(it) : 
FetchUserType(it);
+        identifier_t actual_type = it->itUserlandPort ? 
"mach_port_name_inlined_t" : type;
         const u_int size_bytes = it->itSize >> 3;
         fprintf(file, "\t_Static_assert(sizeof(%s) == %d * %d, \"expected %s 
to be size %d * %d\");\n",
-                      type, size_bytes, it->itNumber,
-                      type, size_bytes, it->itNumber);
+                      actual_type, size_bytes, it->itNumber,
+                      actual_type, size_bytes, it->itNumber);
     }
 }
 
-- 
2.39.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]