aboutsummaryrefslogtreecommitdiffstats
path: root/os-posix.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-06-01 17:23:23 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-06-01 17:24:00 +0200
commit2e5feede9978fadb969c8cfa82b761a8446bf012 (patch)
treee9dbb51e71a14aa9118f8e9c980d4722abb04fd8 /os-posix.c
parenta45e3e024836d7fbfb34d0b62f962a706d1b05fd (diff)
parent406a59bd0a2e7a38cd840a5c08602e3a36bd2df8 (diff)
downloadexternal_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.zip
external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.gz
external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.bz2
upstream integration
This patch is a merge of a series of 42 upstream integration patches into the emulator's master branch. The individual patches come from the 'upstream-integrate' branch that was uploaded separately on kernel.org. The reference upstream sources used for this integration come from http://meego.gitorious.org/qemu-maemo/qemu using the following hash: 7243fbd089cce3c06ca24ed173a251f32644863c In a nutshell, the goal is to make our source tree closer to upstream in order to use various improvement there. Unfortunately, we're not to the point where we can use the upstream ARMv7-A / NEON translator, though we're getting close. Major changes are: - integrate upstream TCG and softfloat - target-arm: Move most Android-specific helper functions to helper-android.c and translate-android.h. This is in preparation of a _major_ integration of the upstream ARM translator. - moving various functions to different files (e.g. cpus.c, qemu-os-posix.c, qemu-os-win32.c, arch_init.c, etc) - qemu-char-android.c is now gone. We're using qemu-char.c with slight modifications embedded within CONFIG_ANDROID-guarded ifdef blocks. - rename "trace.h" to "android-trace.h". We still need to keep "trace.h" and "trace_common.h" until we also update sdk/emulator/tools/qtools/ to use the new header names. After this, we will integrate in a future integration the auto-generated trace.h used by upstream. - remove the OutputChannel hack. Instead, implement a "fake Monitor" object that can be used with any function that takes a Monitor as input. The fake Monitor is used to collect output into a dynamic buffer (e.g. during snapshot save/load). - convert to upstream QEMUTimer API changes. - implement physical memory with RAMBlock lists (instead of a single array). Short log of individual changes: 406a59b trace.h: rename to trace-android.h 288208c target-arm/translate.c: move Android-specific stuff out. f1d9bf1 tcg: integrate upstream version 280afa0 ramblocks: integrate upstream implementation (sophisticated) ae3098a vl-android.c: move arch-specific functions to arch_init.c 23ca2ae vl-android.c: move cpu functions to cpus.c c1ac40a vl-android.c: use os-specific setup routines e49c3f3 compatfd.c: minor integrate 4276038 cpu-exec.c: minor integrate 3b2846a qemu-char-android.c: rename to qemu-char.c f645f7d cpu_restore_state: remove un-necessary argument. f0753ac qjson.c: minor integrate 8354d2d vl-android.c: Move code to iohandler.c d3d4468 translate-all.c: minor integrate 1f9ec0f qemu-config.c: minor integrate d09775c monitor.c: minor integrate 9f64011 disas.c: minor integrate 69ed952 device_tree.c: minor integrate e1c0948 bswap.h + others: minor integrate 6b9236d buffered_file.c: minor integrate 95a83ce savevm: Remove OutputBuffer hack. 986acc9 savevm.c: minor integrate 39373b1 arm-semi.c: minor integrate fb955c7 README: minor integrate 8ee4e5e trace: simplify code and avoid conflicts 65d1521 acl.c: minor integrate c98cf7b arm-dis.c: minor integrate bfec547 fpu: upstream integrate 9bfb3d5 json-lexer.c, json-parser.c: minor integrate 6eaacfb trace.h: minor C compatibility fixes. 17410ee qemu-char.h, console.h: upstream integration 5973c77 qemu-timer.c: rename qemu_timer_new_scale() 317c9d5 qemu-timer.c: upstream integrate 47dc1f4 qerror: minor integrate 488bfd5 qemu-error: minor integrate 1646b4e posix-aio-compat.c: minor integrate 088edf8 os-posix.c + os-win32.c and dependencies 795bb19 qemu-common.h: other intergrates 45c3be0 integrate: qemu-common.h changes Change-Id: If5771dd4b030c602b99845d7489d1f55406bf159
Diffstat (limited to 'os-posix.c')
-rw-r--r--os-posix.c398
1 files changed, 398 insertions, 0 deletions
diff --git a/os-posix.c b/os-posix.c
new file mode 100644
index 0000000..324bf13
--- /dev/null
+++ b/os-posix.c
@@ -0,0 +1,398 @@
+/*
+ * os-posix.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+/*needed for MAP_POPULATE before including qemu-options.h */
+#include <sys/mman.h>
+#include <pwd.h>
+#include <libgen.h>
+
+/* Needed early for CONFIG_BSD etc. */
+#include "config-host.h"
+#include "sysemu.h"
+#include "net.h"
+#include "qemu-options.h"
+
+#ifdef CONFIG_LINUX
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#endif
+
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+static struct passwd *user_pwd;
+static const char *chroot_dir;
+static int daemonize;
+static int fds[2];
+
+void os_setup_early_signal_handling(void)
+{
+ struct sigaction act;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+}
+
+static void termsig_handler(int signal)
+{
+ qemu_system_shutdown_request();
+}
+
+static void sigchld_handler(int signal)
+{
+ waitpid(-1, NULL, WNOHANG);
+}
+
+void os_setup_signal_handling(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = termsig_handler;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+
+ act.sa_handler = sigchld_handler;
+ act.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &act, NULL);
+}
+
+/* Find a likely location for support files using the location of the binary.
+ For installed binaries this will be "$bindir/../share/qemu". When
+ running from the build tree this will be "$bindir/../pc-bios". */
+#define SHARE_SUFFIX "/share/qemu"
+#define BUILD_SUFFIX "/pc-bios"
+char *os_find_datadir(const char *argv0)
+{
+ char *dir;
+ char *p = NULL;
+ char *res;
+ char buf[PATH_MAX];
+ size_t max_len;
+
+#if defined(__linux__)
+ {
+ int len;
+ len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (len > 0) {
+ buf[len] = 0;
+ p = buf;
+ }
+ }
+#elif defined(__FreeBSD__)
+ {
+ static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ size_t len = sizeof(buf) - 1;
+
+ *buf = '\0';
+ if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
+ *buf) {
+ buf[sizeof(buf) - 1] = '\0';
+ p = buf;
+ }
+ }
+#endif
+ /* If we don't have any way of figuring out the actual executable
+ location then try argv[0]. */
+ if (!p) {
+ p = realpath(argv0, buf);
+ if (!p) {
+ return NULL;
+ }
+ }
+ dir = dirname(p);
+ dir = dirname(dir);
+
+ max_len = strlen(dir) +
+ MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
+ res = qemu_mallocz(max_len);
+ snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+ if (access(res, R_OK)) {
+ snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
+ if (access(res, R_OK)) {
+ qemu_free(res);
+ res = NULL;
+ }
+ }
+
+ return res;
+}
+#undef SHARE_SUFFIX
+#undef BUILD_SUFFIX
+
+void os_set_proc_name(const char *s)
+{
+#if defined(PR_SET_NAME)
+ char name[16];
+ if (!s)
+ return;
+ name[sizeof(name) - 1] = 0;
+ strncpy(name, s, sizeof(name));
+ /* Could rewrite argv[0] too, but that's a bit more complicated.
+ This simple way is enough for `top'. */
+ if (prctl(PR_SET_NAME, name)) {
+ perror("unable to change process name");
+ exit(1);
+ }
+#else
+ fprintf(stderr, "Change of process name not supported by your OS\n");
+ exit(1);
+#endif
+}
+
+/*
+ * Parse OS specific command line options.
+ * return 0 if option handled, -1 otherwise
+ */
+void os_parse_cmd_args(int index, const char *optarg)
+{
+ switch (index) {
+#ifdef CONFIG_SLIRP
+ case QEMU_OPTION_smb:
+#if 1
+ net_slirp_smb(optarg);
+#else
+ if (net_slirp_smb(optarg) < 0)
+ exit(1);
+#endif
+ break;
+#endif
+ case QEMU_OPTION_runas:
+ user_pwd = getpwnam(optarg);
+ if (!user_pwd) {
+ fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
+ exit(1);
+ }
+ break;
+ case QEMU_OPTION_chroot:
+ chroot_dir = optarg;
+ break;
+ case QEMU_OPTION_daemonize:
+ daemonize = 1;
+ break;
+ }
+ return;
+}
+
+static void change_process_uid(void)
+{
+ if (user_pwd) {
+ if (setgid(user_pwd->pw_gid) < 0) {
+ fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
+ exit(1);
+ }
+ if (setuid(user_pwd->pw_uid) < 0) {
+ fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
+ exit(1);
+ }
+ if (setuid(0) != -1) {
+ fprintf(stderr, "Dropping privileges failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void change_root(void)
+{
+ if (chroot_dir) {
+ if (chroot(chroot_dir) < 0) {
+ fprintf(stderr, "chroot failed\n");
+ exit(1);
+ }
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
+ }
+
+}
+
+void os_daemonize(void)
+{
+ if (daemonize) {
+ pid_t pid;
+
+ if (pipe(fds) == -1)
+ exit(1);
+
+ pid = fork();
+ if (pid > 0) {
+ uint8_t status;
+ ssize_t len;
+
+ close(fds[1]);
+
+ again:
+ len = read(fds[0], &status, 1);
+ if (len == -1 && (errno == EINTR))
+ goto again;
+
+ if (len != 1)
+ exit(1);
+ else if (status == 1) {
+ fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
+ exit(1);
+ } else
+ exit(0);
+ } else if (pid < 0)
+ exit(1);
+
+ close(fds[0]);
+ qemu_set_cloexec(fds[1]);
+
+ setsid();
+
+ pid = fork();
+ if (pid > 0)
+ exit(0);
+ else if (pid < 0)
+ exit(1);
+
+ umask(027);
+
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ }
+}
+
+void os_setup_post(void)
+{
+ int fd = 0;
+
+ if (daemonize) {
+ uint8_t status = 0;
+ ssize_t len;
+
+ again1:
+ len = write(fds[1], &status, 1);
+ if (len == -1 && (errno == EINTR))
+ goto again1;
+
+ if (len != 1)
+ exit(1);
+
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
+ TFR(fd = qemu_open("/dev/null", O_RDWR));
+ if (fd == -1)
+ exit(1);
+ }
+
+ change_root();
+ change_process_uid();
+
+ if (daemonize) {
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+
+ close(fd);
+ }
+}
+
+void os_pidfile_error(void)
+{
+ if (daemonize) {
+ uint8_t status = 1;
+ if (write(fds[1], &status, 1) != 1) {
+ perror("daemonize. Writing to pipe\n");
+ }
+ } else
+ fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+}
+
+void os_set_line_buffering(void)
+{
+ setvbuf(stdout, NULL, _IOLBF, 0);
+}
+
+/*
+ * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
+ */
+int qemu_eventfd(int fds[2])
+{
+#ifdef CONFIG_EVENTFD
+ int ret;
+
+ ret = eventfd(0, 0);
+ if (ret >= 0) {
+ fds[0] = ret;
+ qemu_set_cloexec(ret);
+ if ((fds[1] = dup(ret)) == -1) {
+ close(ret);
+ return -1;
+ }
+ qemu_set_cloexec(fds[1]);
+ return 0;
+ }
+
+ if (errno != ENOSYS) {
+ return -1;
+ }
+#endif
+
+ return qemu_pipe(fds);
+}
+
+int qemu_create_pidfile(const char *filename)
+{
+ char buffer[128];
+ int len;
+ int fd;
+
+ fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
+ if (fd == -1) {
+ return -1;
+ }
+ if (lockf(fd, F_TLOCK, 0) == -1) {
+ return -1;
+ }
+ len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
+ if (write(fd, buffer, len) != len) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int qemu_get_thread_id(void)
+{
+#if defined (__linux__)
+ return syscall(SYS_gettid);
+#else
+ return getpid();
+#endif
+}