linux-user: Allow targets to specify a minimum uname release
authorPeter Maydell <peter.maydell@linaro.org>
Tue, 3 Sep 2013 19:12:20 +0000 (20:12 +0100)
committerPeter Maydell <peter.maydell@linaro.org>
Tue, 10 Sep 2013 18:11:29 +0000 (19:11 +0100)
For newer target architectures, glibc can be picky about the kernel
version: for example, it will not run on an aarch64 system unless
the kernel reports itself as at least 3.8.0. Accommodate this by
enhancing the existing support for faking the kernel version so
that each target can optionally specify a minimum version: if
the user doesn't force a specific fake version then we will override
with the minimum required version only if the real host kernel
version is insufficient.

Use this facility to let aarch64 report a minimum of 3.8.0.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1378235544-22290-21-git-send-email-peter.maydell@linaro.org

linux-user/main.c
linux-user/qemu.h
linux-user/syscall.c

index b6e434a2032d619f4f40a9a62a686977d8fec2b4..88383053c8eec80b0becb12b75ae25bf9f3195ed 100644 (file)
@@ -3676,6 +3676,8 @@ int main(int argc, char **argv, char **envp)
     /* Scan interp_prefix dir for replacement files. */
     init_paths(interp_prefix);
 
+    init_qemu_uname_release();
+
     if (cpu_model == NULL) {
 #if defined(TARGET_I386)
 #ifdef TARGET_X86_64
index 4df4fcb8654dd86eaf1e2d0c36f96072c9b69ac8..6ffe5a2dec4f2e983e595a26b8a0c4a659c769cb 100644 (file)
@@ -197,6 +197,7 @@ extern THREAD CPUState *thread_cpu;
 void cpu_loop(CPUArchState *env);
 char *target_strerror(int err);
 int get_osversion(void);
+void init_qemu_uname_release(void);
 void fork_start(void);
 void fork_end(int child);
 
index ea04db1a3eb670b09d1b90644db367bbc025d43b..c62d8754f0ad7657d4d33f10c28ff9fdb6ee25a6 100644 (file)
@@ -4863,12 +4863,35 @@ int host_to_target_waitstatus(int status)
     return status;
 }
 
+static int relstr_to_int(const char *s)
+{
+    /* Convert a uname release string like "2.6.18" to an integer
+     * of the form 0x020612. (Beware that 0x020612 is *not* 2.6.12.)
+     */
+    int i, n, tmp;
+
+    tmp = 0;
+    for (i = 0; i < 3; i++) {
+        n = 0;
+        while (*s >= '0' && *s <= '9') {
+            n *= 10;
+            n += *s - '0';
+            s++;
+        }
+        tmp = (tmp << 8) + n;
+        if (*s == '.') {
+            s++;
+        }
+    }
+    return tmp;
+}
+
 int get_osversion(void)
 {
     static int osversion;
     struct new_utsname buf;
     const char *s;
-    int i, n, tmp;
+
     if (osversion)
         return osversion;
     if (qemu_uname_release && *qemu_uname_release) {
@@ -4878,22 +4901,33 @@ int get_osversion(void)
             return 0;
         s = buf.release;
     }
-    tmp = 0;
-    for (i = 0; i < 3; i++) {
-        n = 0;
-        while (*s >= '0' && *s <= '9') {
-            n *= 10;
-            n += *s - '0';
-            s++;
-        }
-        tmp = (tmp << 8) + n;
-        if (*s == '.')
-            s++;
-    }
-    osversion = tmp;
+    osversion = relstr_to_int(s);
     return osversion;
 }
 
+void init_qemu_uname_release(void)
+{
+    /* Initialize qemu_uname_release for later use.
+     * If the host kernel is too old and the user hasn't asked for
+     * a specific fake version number, we might want to fake a minimum
+     * target kernel version.
+     */
+#ifdef UNAME_MINIMUM_RELEASE
+    struct new_utsname buf;
+
+    if (qemu_uname_release && *qemu_uname_release) {
+        return;
+    }
+
+    if (sys_uname(&buf)) {
+        return;
+    }
+
+    if (relstr_to_int(buf.release) < relstr_to_int(UNAME_MINIMUM_RELEASE)) {
+        qemu_uname_release = UNAME_MINIMUM_RELEASE;
+    }
+#endif
+}
 
 static int open_self_maps(void *cpu_env, int fd)
 {