]> Zhao Yanbai Git Server - minix.git/commitdiff
Kernel: separate userland ABI on kernel page 79/3179/2
authorDavid van Moolenbroek <david@minix3.org>
Mon, 21 Sep 2015 14:52:29 +0000 (14:52 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 23 Sep 2015 12:01:15 +0000 (12:01 +0000)
Currently, the userland ABI uses a single field ('user_sp') far
into the very large 'kinfo' structure on the shared kernel
information page.  This precludes us from modifying or getting
rid of 'kinfo' in the future without breaking userland.  This
patch adds a separate 'kuserinfo' structure to the kernel
information page, with only information that is part of the
userland ABI, in an extensible manner.  Userland now uses this
field if it is present, and falls back to the old field if not.

Change-Id: Ib7b24b53a440f40a2edc28cdfa48447ac2179288

12 files changed:
minix/include/lib.h
minix/include/minix/type.h
minix/kernel/arch/earm/memory.c
minix/kernel/arch/i386/memory.c
minix/kernel/glo.h
minix/kernel/main.c
minix/kernel/usermapped_data.c
minix/lib/libc/sys/kernel_utils.c
minix/lib/libc/sys/stack_utils.c
minix/servers/rs/exec.c
minix/servers/vfs/exec.c
minix/usr.bin/trace/kernel.c

index 5caa03ecbe5b201a10d693862c96b04065303f06..00a8eb586d3916836a1f2cb7b29ba1d320aa4676 100644 (file)
@@ -23,6 +23,8 @@
 
 struct minix_kerninfo *get_minix_kerninfo(void);
 
+vir_bytes minix_get_user_sp(void);
+
 struct ps_strings; /* forward declaration for minix_stack_fill. */
 
 void minix_stack_params(const char *path, char * const *argv,
index 29a2838ae1ea08a7eda7c9792939e8378096c48a..f1dba2a692c395a12adaed102ebe83233b7f365c 100644 (file)
@@ -13,6 +13,7 @@
 #include <sys/sigtypes.h>
 
 #include <stdint.h>
+#include <stddef.h>
 
 /* Type definitions. */
 typedef unsigned int vir_clicks;       /*  virtual addr/length in clicks */
@@ -190,10 +191,32 @@ struct arm_frclock {
        u32_t tcrr;             /* tcrr address */
 };
 
+/* The userland ABI portion of general information exposed by the kernel.
+ * This structure may only ever be extended with new fields!
+ */
+struct kuserinfo {
+       size_t kui_size;        /* size of this structure, for ABI testing */
+       vir_bytes kui_user_sp;  /* initial stack pointer for exec'd process */
+};
+
+/* If MINIX_KIF_USERINFO is set, use this to check for a particular field. */
+#define KUSERINFO_HAS_FIELD(kui,f) \
+       (kui->kui_size >= offsetof(struct kuserinfo, f) + sizeof(kui->f))
+
 struct minix_kerninfo {
-       /* Binaries will depend on the offsets etc. in this
-        * structure, so it can't be changed willy-nilly. In
-        * other words, it is ABI-restricted.
+       /* Binaries will depend on the offsets etc. in this structure, so it
+        * can't be changed willy-nilly. In other words, it is ABI-restricted.
+        * However, various fields are to be used by services only, and are not
+        * to be used by userland directly. For pointers to non-userland-ABI
+        * structures, these structures themselves may be changed without
+        * breaking the userland ABI.
+        *
+        * There is currently one important legacy exception: the 'kinfo'
+        * structure should not be part of the userland ABI, but one of its
+        * fields, "user_sp" at offset 2440, is used by legacy user binaries.
+        * This field has since been moved into the 'kuserinfo' structure, but
+        * it will take another major release before we can start changing the
+        * layout of the 'kinfo' structure.
         */
 #define KERNINFO_MAGIC 0xfc3b84bf
        u32_t kerninfo_magic;
@@ -202,17 +225,17 @@ struct minix_kerninfo {
        u32_t flags_unused2;
        u32_t flags_unused3;
        u32_t flags_unused4;
-       struct kinfo            *kinfo;
+       struct kinfo            *kinfo;                 /* see note above! */
        struct machine          *machine;               /* NOT userland ABI */
        struct kmessages        *kmessages;             /* NOT userland ABI */
        struct loadinfo         *loadinfo;              /* NOT userland ABI */
-       struct minix_ipcvecs    *minix_ipcvecs;
-       u32_t reserved;
+       struct minix_ipcvecs    *minix_ipcvecs;         /* userland ABI */
+       struct kuserinfo        *kuserinfo;             /* userland ABI */
        struct arm_frclock      *arm_frclock;           /* NOT userland ABI */
        volatile struct kclockinfo      *kclockinfo;    /* NOT userland ABI */
-} __packed;
+};
 
-#define MINIX_KIF_IPCVECS      (1L << 0)
+#define MINIX_KIF_IPCVECS      (1L << 0)       /* minix_ipcvecs is valid */
+#define MINIX_KIF_USERINFO     (1L << 1)       /* kuserinfo is valid */
 
 #endif /* _TYPE_H */
-
index 26a8eae21671672d381e395a0d8b0d2516f57a1c..7f29af43b205c4ef4302ad1ff4235c2a59355b55 100644 (file)
@@ -714,6 +714,7 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
                ASSIGN(machine);
                ASSIGN(kmessages);
                ASSIGN(loadinfo);
+               ASSIGN(kuserinfo);
                ASSIGN(arm_frclock);
                ASSIGN(kclockinfo);
 
@@ -723,6 +724,9 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
                minix_kerninfo.kerninfo_magic = KERNINFO_MAGIC;
                minix_kerninfo.minix_feature_flags = minix_feature_flags;
                minix_kerninfo_user = (vir_bytes) FIXEDPTR(&minix_kerninfo);
+
+               minix_kerninfo.ki_flags |= MINIX_KIF_USERINFO;
+
                return OK;
        }
 
index a29e068265741b83e9db6983b606049f826416c7..eac6c34abbf0b25fd198904330fe2b294a90bd1a 100644 (file)
@@ -879,6 +879,7 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
                ASSIGN(machine);
                ASSIGN(kmessages);
                ASSIGN(loadinfo);
+               ASSIGN(kuserinfo);
                ASSIGN(arm_frclock); /* eh, why not. */
                ASSIGN(kclockinfo);
 
@@ -920,6 +921,8 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
                        minix_kerninfo.ki_flags |= MINIX_KIF_IPCVECS;
                }
 
+               minix_kerninfo.ki_flags |= MINIX_KIF_USERINFO;
+
                return OK;
        }
 
index 2bab873e3bb188bfe4a76d346a9abf61de300d60..938105d794362074031ce81073ed3e8666018423 100644 (file)
 #include "debug.h"
 
 /* Kernel information structures. This groups vital kernel information. */
-extern struct kinfo kinfo;               /* kernel information for users */
-extern struct machine machine;           /* machine information for users */
+extern struct kinfo kinfo;               /* kernel information for services */
+extern struct machine machine;           /* machine info for services */
 extern struct kmessages kmessages;       /* diagnostic messages in kernel */
 extern struct loadinfo loadinfo;         /* status of load average */
+extern struct kuserinfo kuserinfo;       /* kernel information for users */
 extern struct arm_frclock arm_frclock;   /* ARM free-running timer info */
 extern struct kclockinfo kclockinfo;     /* clock information */
 extern struct minix_kerninfo minix_kerninfo;
index 1c1e52be8209785d70bfb7103cbb4c3759aea841..691b2a6f56e590e3ab8f0ff000dfb26a25eca16f 100644 (file)
@@ -439,6 +439,10 @@ void cstart()
   /* Initialize various user-mapped structures. */
   memset(&arm_frclock, 0, sizeof(arm_frclock));
 
+  memset(&kuserinfo, 0, sizeof(kuserinfo));
+  kuserinfo.kui_size = sizeof(kuserinfo);
+  kuserinfo.kui_user_sp = kinfo.user_sp;
+
 #ifdef USE_APIC
   value = env_get("no_apic");
   if(value)
index cad2511a8be64eed4f4ee2efce6b042189e7b37c..42cfbedad46bb2b53aa748aed8a68231c98c3c04 100644 (file)
@@ -4,10 +4,12 @@
 struct minix_kerninfo minix_kerninfo __section(".usermapped");
 
 /* Kernel information structures. */
-struct kinfo kinfo __section(".usermapped");           /* kernel information for users */
-struct machine machine __section(".usermapped");       /* machine information for users */
+struct kinfo kinfo __section(".usermapped");           /* kernel information for services */
+struct machine machine __section(".usermapped");       /* machine information for services */
 struct kmessages kmessages __section(".usermapped");   /* diagnostic messages in kernel */
 struct loadinfo loadinfo __section(".usermapped");     /* status of load average */
+struct kuserinfo kuserinfo __section(".usermapped");
+       /* kernel information for users */
 struct arm_frclock arm_frclock __section(".usermapped");
        /* ARM free running timer information */
 struct kclockinfo kclockinfo __section(".usermapped"); /* clock information */
index 38b3f58aeec84ec30352a8512841b919048b4646..38681ab86d92be36a271f16d8c3dc5e52a134b5e 100644 (file)
@@ -1,6 +1,12 @@
 /*
  * This file contains the main routine for retrieval of the kernel information
- * page.
+ * page, as well as abstraction routines for retrieval of specific values from
+ * this kernel-mapped user information structure.  These routines may be used
+ * from both userland and system services, and their accesses are considered to
+ * establish part of the userland ABI.  Do not add routines here that are not
+ * for retrieval of userland ABI fields (e.g., clock information)!  Also, since
+ * these functions are MINIX3 specific, their names should contain - preferably
+ * be prefixed with - "minix_".
  */
 
 #define _MINIX_SYSTEM
@@ -8,6 +14,7 @@
 #include <sys/cdefs.h>
 #include "namespace.h"
 #include <lib.h>
+#include <minix/param.h>
 #include <assert.h>
 
 extern struct minix_kerninfo *_minix_kerninfo;
@@ -23,3 +30,33 @@ get_minix_kerninfo(void)
 
        return _minix_kerninfo;
 }
+
+/*
+ * Obtain the initial stack pointer for a new userland process.  This value
+ * is used by routines that set up the stack when executing a new program.
+ * It is used for userland exec(2) and in various system services.
+ */
+vir_bytes
+minix_get_user_sp(void)
+{
+       struct minix_kerninfo *ki;
+
+       /* All information is obtained from the kernel information page. */
+       ki = get_minix_kerninfo();
+
+       /*
+        * Check whether we can retrieve the user stack pointer value from the
+        * kuserinfo structure.  In general, this test is the correct one to
+        * see whether the kuserinfo structure has a certain field.
+        */
+       if ((ki->ki_flags & MINIX_KIF_USERINFO) &&
+           KUSERINFO_HAS_FIELD(ki->kuserinfo, kui_user_sp)) {
+               return ki->kuserinfo->kui_user_sp;
+       }
+
+       /*
+        * Otherwise, fall back to legacy support: retrieve the value from the
+        * kinfo structure.  This field will eventually be removed.
+        */
+       return ki->kinfo->user_sp;
+}
index 133881acd77aaedd7721527d813abc63a1cb6514..0c8ad9e01bfc9feb79e68d57a42801abb614f30a 100644 (file)
@@ -12,7 +12,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <stddef.h>
-#include <minix/param.h>
 #include <sys/exec_elf.h>
 #include <sys/exec.h>
 
@@ -131,7 +130,7 @@ void minix_stack_fill(const char *path, int argc, char * const *argv,
        size_t const min_size = STACK_MIN_SZ;
 
        /* Virtual address of the stack pointer, in new memory space. */
-       *vsp = get_minix_kerninfo()->kinfo->user_sp - stack_size;
+       *vsp = minix_get_user_sp() - stack_size;
 
        /* Fill in the frame now. */
        fpw = (char **) frame;
index ea332948ee8355ccd87e8ac7c6bd9b95331fe3c2..97442e4bc73fc732e846558c8df208842858f8ba 100644 (file)
@@ -2,7 +2,6 @@
 #include <assert.h>
 #include <sys/exec.h>
 #include <libexec.h>
-#include <minix/param.h>
 #include <machine/vmparam.h>
 
 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
@@ -73,7 +72,7 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
 
        memset(&execi, 0, sizeof(execi));
 
-       execi.stack_high = get_minix_kerninfo()->kinfo->user_sp;
+       execi.stack_high = minix_get_user_sp();
        execi.stack_size = DEFAULT_STACK_LIMIT;
        execi.proc_e = proc_e;
        execi.hdr = exec;
index af65b2bc5f410972f6cad8bf7e4563a6ba7b8f4f..b1049fa3eb35e694201b29648d6c7051e7beed94 100644 (file)
@@ -214,7 +214,7 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len,
 
   /* passed from exec() libc code */
   execi.userflags = 0;
-  execi.args.stack_high = get_minix_kerninfo()->kinfo->user_sp;
+  execi.args.stack_high = minix_get_user_sp();
   execi.args.stack_size = DEFAULT_STACK_LIMIT;
 
   fp->text_size = 0;
index 4931d7ba9753ea6bb6857d609bc82bbf0c41f179..bb84f2b7ad4ae4afb2d519c8853509cdd2adc3d8 100644 (file)
@@ -24,7 +24,6 @@
 #include "kernel/arch/i386/include/archconst.h" /* for the KTS_ constants */
 #endif
 #include <lib.h>
-#include <minix/param.h>
 
 /*
  * Working area.  By obtaining values from the kernel into these local process
@@ -154,7 +153,7 @@ vir_bytes
 kernel_get_stacktop(void)
 {
 
-       return get_minix_kerninfo()->kinfo->user_sp;
+       return minix_get_user_sp();
 }
 
 /*