diff --git a/recipes/qemu/recipe.sh b/recipes/qemu/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..76d854ed2a67c01d734350f8aa42e6a03a327a84
--- /dev/null
+++ b/recipes/qemu/recipe.sh
@@ -0,0 +1,43 @@
+VERSION=3.1.0
+TAR=https://download.qemu.org/qemu-$VERSION.tar.xz
+BUILD_DEPENDS=(curl glib libiconv libpng pcre pixman sdl zlib)
+
+function recipe_version {
+    echo "$VERSION"
+    skip=1
+}
+
+function recipe_update {
+    echo "skipping update"
+    skip=1
+}
+
+function recipe_build {
+    sysroot="$(realpath ../sysroot)"
+    export CFLAGS="-I$sysroot/include"
+    export CPPFLAGS="-I$sysroot/include"
+    export LDFLAGS="-L$sysroot/lib"
+    ./configure \
+        --host="${HOST}" \
+        --prefix=/
+    make -j"$(nproc)"
+    skip=1
+}
+
+function recipe_test {
+    echo "skipping test"
+    skip=1
+}
+
+function recipe_clean {
+    make clean
+    skip=1
+}
+
+function recipe_stage {
+    #export LLVM_CONFIG="x86_64-unknown-redox-llvm-config"
+    dest="$(realpath $1)"
+    make DESTDIR="$dest" install
+    rm -f "$dest/lib/"*.la
+    skip=1
+}
diff --git a/recipes/qemu/redox.patch b/recipes/qemu/redox.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9543ce1ca8b3b43ade8c89ee1e6b2613f6b7228b
--- /dev/null
+++ b/recipes/qemu/redox.patch
@@ -0,0 +1,308 @@
+diff -ruwN source/block/file-posix.c source-new/block/file-posix.c
+--- source/block/file-posix.c	2019-01-13 08:23:04.772397346 -0700
++++ source-new/block/file-posix.c	2019-01-13 10:40:35.102453914 -0700
+@@ -258,6 +258,7 @@
+     int i;
+ 
+     errno = ENOTSUP;
++#if !defined(__redox__)
+     static const unsigned long ioctl_list[] = {
+ #ifdef BLKSSZGET
+         BLKSSZGET,
+@@ -277,6 +278,7 @@
+             success = true;
+         }
+     }
++#endif
+ 
+     return success ? 0 : -errno;
+ }
+@@ -1154,6 +1156,9 @@
+ 
+ static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
+ {
++#if defined(__redox__)
++    return -ENOTSUP
++#else
+     int ret;
+ 
+     ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
+@@ -1162,6 +1167,7 @@
+     }
+ 
+     return 0;
++#endif
+ }
+ 
+ static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
+diff -ruwN source/configure source-new/configure
+--- source/configure	2018-12-11 10:44:34.000000000 -0700
++++ source-new/configure	2019-01-12 15:11:33.069669757 -0700
+@@ -649,6 +649,8 @@
+   targetos='NetBSD'
+ elif check_define __APPLE__; then
+   targetos='Darwin'
++elif check_define __redox__; then
++  targetos='Redox'
+ else
+   # This is a fatal error, but don't report it yet, because we
+   # might be going to just print the --help text, or it might
+@@ -3500,7 +3502,7 @@
+ EOF
+ 
+ if ! compile_prog "$CFLAGS" "$LIBS" ; then
+-    error_exit "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\
++    echo "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\
+                "You probably need to set PKG_CONFIG_LIBDIR"\
+ 	       "to point to the right pkg-config files for your"\
+ 	       "build target"
+diff -ruwN source/include/qom/cpu.h source-new/include/qom/cpu.h
+--- source/include/qom/cpu.h	2018-12-11 10:44:34.000000000 -0700
++++ source-new/include/qom/cpu.h	2019-01-12 15:14:15.442350500 -0700
+@@ -30,6 +30,10 @@
+ #include "qemu/queue.h"
+ #include "qemu/thread.h"
+ 
++#if defined(__redox__)
++#define sigjmp_buf jmp_buf
++#endif
++
+ typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
+                                      void *opaque);
+ 
+diff -ruwN source/io/channel-socket.c source-new/io/channel-socket.c
+--- source/io/channel-socket.c	2018-12-11 10:44:34.000000000 -0700
++++ source-new/io/channel-socket.c	2019-01-13 08:54:26.951009516 -0700
+@@ -407,7 +407,7 @@
+ }
+ 
+ 
+-#ifndef WIN32
++#if !defined(WIN32) && !defined(__redox__)
+ static void qio_channel_socket_copy_fds(struct msghdr *msg,
+                                         int **fds, size_t *nfds)
+ {
+@@ -554,7 +554,7 @@
+     }
+     return ret;
+ }
+-#else /* WIN32 */
++#else /* WIN32 or __redox__ */
+ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
+                                         const struct iovec *iov,
+                                         size_t niov,
+diff -ruwN source/util/compatfd.c source-new/util/compatfd.c
+--- source/util/compatfd.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/compatfd.c	2019-01-12 16:24:40.146857753 -0700
+@@ -17,7 +17,9 @@
+ #include "qemu-common.h"
+ #include "qemu/thread.h"
+ 
++#if defined(CONFIG_SIGNALFD)
+ #include <sys/syscall.h>
++#endif
+ 
+ struct sigfd_compat_info
+ {
+diff -ruwN source/util/coroutine-sigaltstack.c source-new/util/coroutine-sigaltstack.c
+--- source/util/coroutine-sigaltstack.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/coroutine-sigaltstack.c	2019-01-13 10:38:32.279965167 -0700
+@@ -30,6 +30,12 @@
+ #include "qemu-common.h"
+ #include "qemu/coroutine_int.h"
+ 
++#if defined(__redox__)
++#define sigjmp_buf jmp_buf
++#define sigsetjmp(env, savesigs) setjmp(env)
++#define siglongjmp longjmp
++#endif
++
+ typedef struct {
+     Coroutine base;
+     void *stack;
+@@ -288,4 +294,3 @@
+ 
+     return s && s->current->caller;
+ }
+-
+diff -ruwN source/util/iov.c source-new/util/iov.c
+--- source/util/iov.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/iov.c	2019-01-12 16:32:12.067228460 -0700
+@@ -95,7 +95,7 @@
+ static ssize_t
+ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
+ {
+-#ifdef CONFIG_POSIX
++#if defined(CONFIG_POSIX) && !defined(__redox__)
+     ssize_t ret;
+     struct msghdr msg;
+     memset(&msg, 0, sizeof(msg));
+diff -ruwN source/util/main-loop.c source-new/util/main-loop.c
+--- source/util/main-loop.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/main-loop.c	2019-01-13 10:37:48.544674956 -0700
+@@ -35,6 +35,10 @@
+ #include "block/aio.h"
+ #include "qemu/error-report.h"
+ 
++#if defined(__redox__)
++#define pthread_sigmask sigprocmask
++#endif
++
+ #ifndef _WIN32
+ 
+ /* If we have signalfd, we mask out the signals we want to handle and then
+@@ -63,9 +67,12 @@
+         }
+ 
+         sigaction(info.ssi_signo, NULL, &action);
++#if !defined(__redox__)
+         if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
+             sigaction_invoke(&action, &info);
+-        } else if (action.sa_handler) {
++        } else
++#endif
++        if (action.sa_handler) {
+             action.sa_handler(info.ssi_signo);
+         }
+     }
+diff -ruwN source/util/osdep.c source-new/util/osdep.c
+--- source/util/osdep.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/osdep.c	2019-01-13 09:31:50.920247468 -0700
+@@ -138,10 +138,12 @@
+         goto fail;
+     }
+ 
++#if !defined(__redox__)
+     if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
+         errno = EINVAL;
+         goto fail;
+     }
++#endif
+ 
+     /* Set/unset flags that we can with fcntl */
+     if (fcntl(ret, F_SETFL, flags) == -1) {
+@@ -236,6 +238,9 @@
+ 
+ static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
+ {
++#if defined(__redox__)
++    return 0;
++#else
+     int ret;
+     struct flock fl = {
+         .l_whence = SEEK_SET,
+@@ -248,6 +253,7 @@
+         ret = fcntl(fd, fcntl_op_setlk, &fl);
+     } while (ret == -1 && errno == EINTR);
+     return ret == -1 ? -errno : 0;
++#endif
+ }
+ 
+ int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive)
+@@ -262,6 +268,9 @@
+ 
+ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
+ {
++#if defined(__redox__)
++    return 0;
++#else
+     int ret;
+     struct flock fl = {
+         .l_whence = SEEK_SET,
+@@ -276,6 +285,7 @@
+     } else {
+         return fl.l_type == F_UNLCK ? 0 : -EAGAIN;
+     }
++#endif
+ }
+ #endif
+ 
+diff -ruwN source/util/oslib-posix.c source-new/util/oslib-posix.c
+--- source/util/oslib-posix.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/oslib-posix.c	2019-01-12 16:34:05.703955117 -0700
+@@ -36,9 +36,17 @@
+ #include "qapi/error.h"
+ #include "qemu/sockets.h"
+ #include <libgen.h>
++#if !defined(__redox__)
+ #include <sys/signal.h>
++#endif
+ #include "qemu/cutils.h"
+ 
++#if defined(__redox__)
++#define pthread_sigmask sigprocmask
++#define sigsetjmp(env, savesigs) setjmp(env)
++#define siglongjmp longjmp
++#endif
++
+ #ifdef CONFIG_LINUX
+ #include <sys/syscall.h>
+ #endif
+@@ -95,12 +103,13 @@
+ 
+     while (1) {
+         struct stat a, b;
++#if !defined(__redox__)
+         struct flock lock = {
+             .l_type = F_WRLCK,
+             .l_whence = SEEK_SET,
+             .l_len = 0,
+         };
+-
++#endif
+         fd = qemu_open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+         if (fd == -1) {
+             error_setg_errno(errp, errno, "Cannot open pid file");
+@@ -112,10 +121,12 @@
+             goto fail_close;
+         }
+ 
++#if !defined(__redox__)
+         if (fcntl(fd, F_SETLK, &lock)) {
+             error_setg_errno(errp, errno, "Cannot lock pid file");
+             goto fail_close;
+         }
++#endif
+ 
+         /*
+          * Now make sure the path we locked is the same one that now
+@@ -420,7 +431,11 @@
+ 
+ static inline int get_memset_num_threads(int smp_cpus)
+ {
++#if defined(__redox__)
++    long host_procs = 1;
++#else
+     long host_procs = sysconf(_SC_NPROCESSORS_ONLN);
++#endif
+     int ret = 1;
+ 
+     if (host_procs > 0) {
+@@ -682,6 +697,7 @@
+ void sigaction_invoke(struct sigaction *action,
+                       struct qemu_signalfd_siginfo *info)
+ {
++#if !defined(__redox__)
+     siginfo_t si = {};
+     si.si_signo = info->ssi_signo;
+     si.si_errno = info->ssi_errno;
+@@ -708,4 +724,5 @@
+         si.si_uid = info->ssi_uid;
+     }
+     action->sa_sigaction(info->ssi_signo, &si, NULL);
++#endif
+ }
+diff -ruwN source/util/qemu-progress.c source-new/util/qemu-progress.c
+--- source/util/qemu-progress.c	2018-12-11 10:44:35.000000000 -0700
++++ source-new/util/qemu-progress.c	2019-01-13 10:34:53.704639662 -0700
+@@ -25,6 +25,10 @@
+ #include "qemu/osdep.h"
+ #include "qemu-common.h"
+ 
++#if defined(__redox__)
++#define pthread_sigmask sigprocmask
++#endif
++
+ struct progress_state {
+     float current;
+     float last_print;