aboutsummaryrefslogtreecommitdiff
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2013-09-03 20:12:20 +0100
committerPeter Maydell <peter.maydell@linaro.org>2013-09-10 19:11:29 +0100
commit4a24a758101ff726c9bd3b867e12d5580c793af0 (patch)
tree575f2f44eb438836946a138a80dac396b0173968 /linux-user/syscall.c
parentaf89c7dba52c509bdb72714139aadbe21a133f6e (diff)
linux-user: Allow targets to specify a minimum uname release
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
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ea04db1a3e..c62d8754f0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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)
{