diff --git a/.travis.yml b/.travis.yml
index ce62ef531688cfafb355240e3b5d0d7961db2f14..e258303a5337c7ae136386cd7a965f9da8afd0de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,65 +1,106 @@
 language: rust
 sudo: required
 dist: trusty
-rust:
-  - 1.0.0
-  - stable
-  - beta
-  - nightly
 services:
   - docker
+install:
+  - curl https://static.rust-lang.org/rustup.sh |
+    sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
 script:
-  - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then
-      sh ci/run-travis.sh;
-    elif [[ $TRAVIS_RUST_VERSION = "1.0.0" ]]; then
-      cargo build;
+  - cargo build
+  - cargo build --no-default-features
+  - cargo generate-lockfile --manifest-path libc-test/Cargo.toml
+  - if [[ $TRAVIS_OS_NAME = "linux" ]]; then
+      sh ci/run-docker.sh $TARGET;
     else
-      cargo build &&
-      cargo build --no-default-features &&
-      rustc ci/style.rs && ./style src;
+      export CARGO_TARGET_DIR=`pwd`/target;
+      sh ci/run.sh $TARGET;
     fi
+  - rustc ci/style.rs && ./style src
 osx_image: xcode7.3
-os:
-  - linux
-  - osx
 env:
-  matrix:
-    - ARCH=x86_64
-    - ARCH=i686
   global:
     secure: eIDEoQdTyglcsTD13zSGotAX2HDhRSXIaaTnVZTThqLSrySOc3/6KY3qmOc2Msf7XaBqfFy9QA+alk7OwfePp253eiy1Kced67ffjjFOytEcRT7FlQiYpcYQD6WNHZEj62/bJBO4LTM9sGtWNCTJVEDKW0WM8mUK7qNuC+honPM=
 matrix:
   include:
+    # 1.0.0 compat
     - os: linux
-      env: TARGET=arm-linux-androideabi DOCKER=alexcrichton/rust-slave-android:2015-11-22
-      rust: nightly
+      env: TARGET=x86_64-unknown-linux-gnu
+      rust: 1.0.0
+      script: cargo build
+      install:
+
+    # build documentation
+    - os: linux
+      env: TARGET=x86_64-unknown-linux-gnu
+      rust: stable
+      script: sh ci/dox.sh
+
+    # stable compat
+    - os: linux
+      env: TARGET=x86_64-unknown-linux-gnu
+      rust: stable
+    - os: linux
+      env: TARGET=i686-unknown-linux-gnu
+      rust: stable
+    - os: osx
+      env: TARGET=x86_64-apple-darwin
+      rust: stable
+    - os: osx
+      env: TARGET=i686-apple-darwin
+      rust: stable
+    - os: linux
+      env: TARGET=arm-linux-androideabi
+      rust: stable
     - os: linux
       env: TARGET=x86_64-unknown-linux-musl
-      rust: nightly
+      rust: stable
     - os: linux
       env: TARGET=arm-unknown-linux-gnueabihf
-      rust: nightly
-    - os: linux
-      env: TARGET=mips-unknown-linux-gnu DOCKER=alexcrichton/rust-libc-mips:2016-01-10
-      rust: nightly
+      rust: stable
     - os: linux
       env: TARGET=aarch64-unknown-linux-gnu
-      rust: nightly
+      rust: stable
     - os: osx
       env: TARGET=i386-apple-ios
-      rust: nightly
+      rust: stable
     - os: osx
       env: TARGET=x86_64-apple-ios
-      rust: nightly
+      rust: stable
+    - os: linux
+      env: TARGET=x86_64-rumprun-netbsd
+      rust: stable
+
+    # beta
+    - os: linux
+      env: TARGET=x86_64-unknown-linux-gnu
+      rust: beta
+    - os: osx
+      env: TARGET=x86_64-apple-darwin
+      rust: beta
+
+    # nightly
     - os: linux
-      env: TARGET=x86_64-rumprun-netbsd DOCKER=alexcrichton/rust-libc-rumprun:2015-11-27
+      env: TARGET=x86_64-unknown-linux-gnu
+      rust: nightly
+    - os: osx
+      env: TARGET=x86_64-apple-darwin
       rust: nightly
     - os: linux
-      env: TARGET=x86_64-unknown-freebsd QEMU=freebsd.qcow2
+      env: TARGET=mips-unknown-linux-gnu
+      # not sure why this has to be nightly...
       rust: nightly
+
+    # QEMU based targets that compile in an emulator
+    - os: linux
+      env: TARGET=x86_64-unknown-freebsd
+      rust: stable
     - os: linux
       env: TARGET=x86_64-unknown-openbsd QEMU=openbsd.qcow2
-      rust: nightly
+      rust: stable
+      script: sh ci/run-docker.sh $TARGET
+      install:
+
 notifications:
   email:
     on_success: never
diff --git a/ci/cargo-config b/ci/cargo-config
deleted file mode 100644
index 41e232e5460620e382928055ea8c86df510da320..0000000000000000000000000000000000000000
--- a/ci/cargo-config
+++ /dev/null
@@ -1,13 +0,0 @@
-# Configuration of which linkers to call on Travis for various architectures
-
-[target.arm-linux-androideabi]
-linker = "arm-linux-androideabi-gcc"
-
-[target.arm-unknown-linux-gnueabihf]
-linker = "arm-linux-gnueabihf-gcc-4.7"
-
-[target.mips-unknown-linux-gnu]
-linker = "mips-linux-gnu-gcc-5"
-
-[target.aarch64-unknown-linux-gnu]
-linker = "aarch64-linux-gnu-gcc"
diff --git a/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1c7235cd0d1e5b01ae34c3d22346743556b76002
--- /dev/null
+++ b/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
@@ -0,0 +1,7 @@
+FROM ubuntu:14.04
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc libc6-dev ca-certificates \
+  gcc-aarch64-linux-gnu libc6-dev-arm64-cross qemu-user
+ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
+    PATH=$PATH:/rust/bin
diff --git a/ci/docker/arm-linux-androideabi/Dockerfile b/ci/docker/arm-linux-androideabi/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..0e41ba6dbee66dc1301797cecb7c73a4bc4e1b56
--- /dev/null
+++ b/ci/docker/arm-linux-androideabi/Dockerfile
@@ -0,0 +1,4 @@
+FROM alexcrichton/rust-slave-android:2015-11-22
+ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
+    PATH=$PATH:/rust/bin
+ENTRYPOINT ["sh"]
diff --git a/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..3a858e3884a3d6241b33cd112f5e0f5bec58918f
--- /dev/null
+++ b/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
@@ -0,0 +1,7 @@
+FROM ubuntu:16.04
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc libc6-dev ca-certificates \
+  gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user
+ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
+    PATH=$PATH:/rust/bin
diff --git a/ci/docker/i686-unknown-linux-gnu/Dockerfile b/ci/docker/i686-unknown-linux-gnu/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..63450ff9e0efc793a850738a007d18e68c5cae3f
--- /dev/null
+++ b/ci/docker/i686-unknown-linux-gnu/Dockerfile
@@ -0,0 +1,5 @@
+FROM ubuntu:16.04
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc-multilib libc6-dev ca-certificates
+ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/mips-unknown-linux-gnu/Dockerfile b/ci/docker/mips-unknown-linux-gnu/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..8eb6a26b00a5517d2e32c6344b16675801392885
--- /dev/null
+++ b/ci/docker/mips-unknown-linux-gnu/Dockerfile
@@ -0,0 +1,13 @@
+FROM ubuntu:15.10
+
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+        software-properties-common gcc libc6-dev qemu-user
+RUN add-apt-repository ppa:angelsl/mips-cross
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+        gcc-5-mips-linux-gnu libc6-dev-mips-cross
+
+ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc-5 \
+    CC_mips_unknown_linux_gnu=mips-linux-gnu-gcc-5 \
+    PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-rumprun-netbsd/Dockerfile b/ci/docker/x86_64-rumprun-netbsd/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..129771e76b74d7b843ca9e30f378146ea97e2ec2
--- /dev/null
+++ b/ci/docker/x86_64-rumprun-netbsd/Dockerfile
@@ -0,0 +1,6 @@
+FROM mato/rumprun-toolchain-hw-x86_64
+USER root
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  qemu
+ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-unknown-freebsd/Dockerfile b/ci/docker/x86_64-unknown-freebsd/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..bffcaa0ced30bc232ebd1809d4b7958ff10577e9
--- /dev/null
+++ b/ci/docker/x86_64-unknown-freebsd/Dockerfile
@@ -0,0 +1,13 @@
+FROM alexcrichton/rust-slave-linux-cross:2016-04-15
+USER root
+
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  qemu qemu-kvm kmod cpu-checker
+
+ENTRYPOINT ["sh"]
+
+ENV PATH=$PATH:/rust/bin \
+    QEMU=freebsd.qcow2 \
+    CAN_CROSS=1 \
+    CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER=x86_64-unknown-freebsd10-gcc
diff --git a/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..294a0621ce946bf144a7f0af10a4ba3c2901cd12
--- /dev/null
+++ b/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
@@ -0,0 +1,5 @@
+FROM ubuntu:16.04
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc libc6-dev ca-certificates
+ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/ci/docker/x86_64-unknown-linux-musl/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..f44003806e5946da325d6e60996b5a7482ca1fa4
--- /dev/null
+++ b/ci/docker/x86_64-unknown-linux-musl/Dockerfile
@@ -0,0 +1,13 @@
+FROM ubuntu:16.04
+
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc make libc6-dev git curl ca-certificates
+RUN curl https://www.musl-libc.org/releases/musl-1.1.14.tar.gz | \
+    tar xzf - && \
+    cd musl-1.1.14 && \
+    ./configure --prefix=/musl-x86_64 && \
+    make install -j4 && \
+    cd .. && \
+    rm -rf musl-1.1.14
+ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin
diff --git a/ci/docker/x86_64-unknown-openbsd/Dockerfile b/ci/docker/x86_64-unknown-openbsd/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..f0343c13618fb205464db645bf7d643716df550a
--- /dev/null
+++ b/ci/docker/x86_64-unknown-openbsd/Dockerfile
@@ -0,0 +1,7 @@
+FROM ubuntu:16.04
+
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+  gcc libc6-dev qemu qemu-kvm curl ca-certificates kmod cpu-checker
+ENV PATH=$PATH:/rust/bin \
+    QEMU=openbsd.qcow2
diff --git a/ci/mips/Dockerfile b/ci/mips/Dockerfile
deleted file mode 100644
index 6da6f684c0ddb61b5098020c09fc3e096e7709d7..0000000000000000000000000000000000000000
--- a/ci/mips/Dockerfile
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM ubuntu:15.10
-
-RUN apt-get update
-RUN apt-get install -y --force-yes --no-install-recommends \
-        software-properties-common
-RUN add-apt-repository ppa:angelsl/mips-cross
-RUN apt-get update
-RUN apt-get install -y --force-yes --no-install-recommends \
-        gcc-5-mips-linux-gnu libc6-dev-mips-cross \
-        gcc-5-mipsel-linux-gnu libc6-dev-mipsel-cross
-RUN apt-get install -y --force-yes --no-install-recommends \
-                build-essential qemu-user
diff --git a/ci/rumprun/Dockerfile b/ci/rumprun/Dockerfile
deleted file mode 100644
index 16c7d375c2f12395d3748ac399c52b3468590322..0000000000000000000000000000000000000000
--- a/ci/rumprun/Dockerfile
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM ubuntu:15.04
-
-RUN apt-get update
-RUN apt-get install -y binutils git g++ make qemu
-
-WORKDIR /build
-RUN git clone --recursive http://repo.rumpkernel.org/rumprun
-WORKDIR /build/rumprun
-RUN CC=cc ./build-rr.sh hw
-
-ENV PATH=$PATH:/build/rumprun/rumprun/bin
-WORKDIR /root
diff --git a/ci/run-all.sh b/ci/run-all.sh
deleted file mode 100644
index 915c54cbe19beebce2100bb22dc6bca9c3f93583..0000000000000000000000000000000000000000
--- a/ci/run-all.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-# This is **not** meant to be run on CI, but rather locally instead. If you're
-# on a Linux machine you'll be able to run most of these, but otherwise this'll
-# just attempt to run as many platforms as possible!
-
-run() {
-    _target=$1
-    _cc=$2
-    if [ "$_cc" != "" ]; then
-        which $_cc > /dev/null
-        if [ $? -ne 0 ]; then
-           echo "$_cc not installed, skipping $_target"
-           return
-        fi
-        export CC=$_cc
-    fi
-    if [ ! -d .cargo ]; then
-        mkdir .cargo
-        cp ci/cargo-config .cargo/config
-    fi
-    sh ci/run.sh $_target
-    if [ "$?" != "0" ]; then
-        exit 1
-    fi
-}
-
-OS=`uname`
-if [ "$OS" = "Linux" ]; then
-    # For more info on where to get all these cross compilers see
-    # ci/run-travis.sh and what packages are needed on ubuntu
-    run x86_64-unknown-linux-gnu clang
-    run i686-unknown-linux-gnu clang
-    run x86_64-unknown-linux-musl musl-gcc
-    run mips-unknown-linux-gnu mips-linux-gnu-gcc
-    run aarch64-unknown-linux-gnu aarch64-linux-gnueabihf-gcc
-    run arm-unknown-linux-gnueabihf arm-linux-gnueabihf-gcc-4.7
-
-    # Prep for this by running `vagrant up freebsd` in the `ci` directory
-    (cd ci && vagrant ssh freebsd -c \
-        "cd /vagrant && sh ci/run.sh x86_64-unknown-freebsd")
-
-    # Make sure you've run `docker pull alexcrichton/rust-libc-test` to get
-    # this image ahead of time.
-    docker run -itv `pwd`:/clone alexcrichton/rust-libc-test \
-        sh ci/run.sh arm-linux-androideabi
-elif [ "$OS" = "Darwin" ]; then
-    cargo run --target x86_64-unknown-linux-gnu
-    cargo run --target i686-unknown-linux-gnu
-fi
diff --git a/ci/run-docker.sh b/ci/run-docker.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5ad90652f0d869727d93342afaf5c4047f7c2b1e
--- /dev/null
+++ b/ci/run-docker.sh
@@ -0,0 +1,25 @@
+# Small script to run tests for a target (or all targets) inside all the
+# respective docker images.
+
+set -ex
+
+run() {
+    echo $1
+    docker build -t libc ci/docker/$1
+    docker run \
+      -v `rustc --print sysroot`:/rust:ro \
+      -v `pwd`:/checkout:ro \
+      -e CARGO_TARGET_DIR=/tmp/target \
+      -w /checkout \
+      --privileged \
+      -it libc \
+      ci/run.sh $1
+}
+
+if [ -z "$1" ]; then
+  for d in `ls ci/docker/`; do
+    run $d
+  done
+else
+  run $1
+fi
diff --git a/ci/run-qemu.sh b/ci/run-qemu.sh
index 78da64aa8fb17190d38eabc553581a886f7cd3b1..70f312e3bd5f1c478a0410d6ca3da652bc864bb1 100644
--- a/ci/run-qemu.sh
+++ b/ci/run-qemu.sh
@@ -15,12 +15,9 @@ cp -r $ROOT/libc /tmp/libc
 cd /tmp/libc
 
 TARGET=$(cat $ROOT/TARGET)
+export CARGO_TARGET_DIR=/tmp
 
 case $TARGET in
-  *-freebsd)
-    sudo pkg install -y rust cargo
-    ;;
-
   *-openbsd)
     pkg_add rust curl gcc-4.8.4p4
     curl https://static.rust-lang.org/cargo-dist/2015-04-02/cargo-nightly-x86_64-unknown-openbsd.tar.gz | \
diff --git a/ci/run-travis.sh b/ci/run-travis.sh
deleted file mode 100644
index 3881e6ea0b01bd73eb0b271f95e170760dd5f87b..0000000000000000000000000000000000000000
--- a/ci/run-travis.sh
+++ /dev/null
@@ -1,188 +0,0 @@
-# Entry point for all travis builds, this will set up the Travis environment by
-# downloading any dependencies. It will then execute the `run.sh` script to
-# build and execute all tests.
-#
-# For a full description of how all tests are run, see `ci/README.md`
-
-set -ex
-
-if [ "$TRAVIS_OS_NAME" = "linux" ]; then
-  OS=unknown-linux-gnu
-else
-  OS=apple-darwin
-fi
-
-export HOST=$ARCH-$OS
-if [ "$TARGET" = "" ]; then
-  TARGET=$HOST
-fi
-
-MAIN_TARGETS=https://static.rust-lang.org/dist
-DATE=$(echo $TRAVIS_RUST_VERSION | sed s/nightly-//)
-if [ "$DATE" != "nightly" ]; then
-    MAIN_TARGETS=$MAIN_TARGETS/$DATE
-    TRAVIS_RUST_VERSION=nightly
-fi
-
-install() {
-  if [ "$TRAVIS" = "true" ]; then
-    sudo apt-get update
-    sudo apt-get install -y $@
-  fi
-}
-
-# If we're going to run tests inside of a qemu image, then we don't need any of
-# the scripts below. Instead, download the image, prepare a filesystem which has
-# the current state of this repository, and then run the image.
-#
-# It's assume that all images, when run with two disks, will run the `run.sh`
-# script from the second which we place inside.
-if [ "$QEMU" != "" ]; then
-  # Acquire QEMU and the base OS image
-  install qemu-kvm
-  tmpdir=/tmp/qemu-img-creation
-  mkdir -p $tmpdir
-  if [ ! -f $tmpdir/$QEMU ]; then
-    curl https://people.mozilla.org/~acrichton/libc-test/qemu/$QEMU.gz | \
-      gunzip -d > $tmpdir/$QEMU
-  fi
-
-  # Generate all.{c,rs} on the host which will be compiled inside QEMU. Do this
-  # here because compiling syntex_syntax in QEMU would time out basically
-  # everywhere.
-  rm -rf $tmpdir/generated
-  mkdir -p $tmpdir/generated
-  CARGO_TARGET_DIR=$tmpdir/generated-build \
-    cargo build --manifest-path libc-test/generate-files/Cargo.toml
-  (cd libc-test && TARGET=$TARGET OUT_DIR=$tmpdir/generated SKIP_COMPILE=1 \
-    $tmpdir/generated-build/debug/generate-files)
-
-  # Create a mount a fresh new filesystem image that we'll later pass to QEMU,
-  # this contains the checkout of libc and will be able to run all tests
-  rm -f $tmpdir/libc-test.img
-  dd if=/dev/null of=$tmpdir/libc-test.img bs=1M seek=5
-  mkfs.ext2 -F $tmpdir/libc-test.img
-  rm -rf $tmpdir/mount
-  mkdir $tmpdir/mount
-  sudo mount -t ext2 -o loop $tmpdir/libc-test.img $tmpdir/mount
-
-  # Copy this folder into the mounted image, the `run.sh` entry point, and
-  # overwrite the standard libc-test Cargo.toml with the overlay one which will
-  # assume the all.{c,rs} test files have already been generated
-  sudo mkdir $tmpdir/mount/libc
-  sudo cp -r * $tmpdir/mount/libc/
-  sudo cp ci/run-qemu.sh $tmpdir/mount/run.sh
-  echo $TARGET | sudo tee -a $tmpdir/mount/TARGET
-  sudo cp $tmpdir/generated/* $tmpdir/mount/libc/libc-test
-  sudo cp libc-test/run-generated-Cargo.toml $tmpdir/mount/libc/libc-test/Cargo.toml
-
-  sudo umount $tmpdir/mount
-
-  # If we can use kvm, prefer that, otherwise just fall back to user-space
-  # emulation.
-  if kvm-ok; then
-    program="sudo kvm"
-  else
-    program=qemu-system-x86_64
-  fi
-
-  # Pass -snapshot to prevent tampering with the disk images, this helps when
-  # running this script in development. The two drives are then passed next,
-  # first is the OS and second is the one we just made. Next the network is
-  # configured to work (I'm not entirely sure how), and then finally we turn off
-  # graphics and redirect the serial console output to out.log.
-  $program \
-    -m 1024 \
-    -snapshot \
-    -drive if=virtio,file=$tmpdir/$QEMU \
-    -drive if=virtio,file=$tmpdir/libc-test.img \
-    -net nic,model=virtio \
-    -net user \
-    -nographic \
-    -vga none 2>&1 | tee out.log
-  exec grep "^PASSED .* tests" out.log
-fi
-
-mkdir -p .cargo
-cp ci/cargo-config .cargo/config
-
-# Next up we need to install the standard library for the version of Rust that
-# we're testing.
-if [ "$TRAVIS" = "true" ]; then
-  curl https://static.rust-lang.org/rustup.sh | \
-    sh -s -- --add-target=$TARGET --disable-sudo -y \
-      --prefix=`rustc --print sysroot`
-fi
-
-# If we're testing with a docker image, then run tests entirely within that
-# image. Note that this is using the same rustc installation that travis has
-# (sharing it via `-v`) and otherwise the tests run entirely within the
-# container.
-#
-# For the docker build we mount the entire current directory at /checkout, set
-# up some environment variables to let it run, and then run the standard run.sh
-# script.
-if [ "$DOCKER" != "" ]; then
-  args=""
-
-  case "$TARGET" in
-    mips-unknown-linux-gnu)
-      args="$args -e CC=mips-linux-gnu-gcc-5"
-      ;;
-
-    *)
-      ;;
-  esac
-
-  exec docker run \
-    --entrypoint bash \
-    -v `rustc --print sysroot`:/usr/local:ro \
-    -v `pwd`:/checkout \
-    -e LD_LIBRARY_PATH=/usr/local/lib \
-    -e CARGO_TARGET_DIR=/tmp \
-    $args \
-    -w /checkout \
-    -it $DOCKER \
-    ci/run.sh $TARGET
-fi
-
-# If we're not running docker or qemu, then we may still need some packages
-# and/or tools with various configurations here and there.
-case "$TARGET" in
-  x86_64-unknown-linux-musl)
-    install musl-tools
-    export CC=musl-gcc
-    ;;
-
-  arm-unknown-linux-gnueabihf)
-    install gcc-4.7-arm-linux-gnueabihf qemu-user
-    export CC=arm-linux-gnueabihf-gcc-4.7
-    ;;
-
-  aarch64-unknown-linux-gnu)
-    install gcc-aarch64-linux-gnu qemu-user
-    export CC=aarch64-linux-gnu-gcc
-    ;;
-
-  *-apple-ios)
-    ;;
-
-  *)
-    # clang has better error messages and implements alignof more broadly
-    export CC=clang
-
-    if [ "$TARGET" = "i686-unknown-linux-gnu" ]; then
-      install gcc-multilib
-    fi
-    ;;
-
-esac
-
-# Finally, if we've gotten this far, actually run the tests.
-sh ci/run.sh $TARGET
-
-if [ "$TARGET" = "x86_64-unknown-linux-gnu" ] && \
-   [ "$TRAVIS_RUST_VERSION" = "nightly" ] && \
-   [ "$TRAVIS_OS_NAME" = "linux" ]; then
-  sh ci/dox.sh
-fi
diff --git a/ci/run.sh b/ci/run.sh
old mode 100644
new mode 100755
index 706bf7a1d1ccdaf7a065e37127342079e5973e8b..aea1de8dfec24bb7251204e4eb6b7ff8993d23ab
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -6,6 +6,89 @@
 set -ex
 
 TARGET=$1
+
+# If we're going to run tests inside of a qemu image, then we don't need any of
+# the scripts below. Instead, download the image, prepare a filesystem which has
+# the current state of this repository, and then run the image.
+#
+# It's assume that all images, when run with two disks, will run the `run.sh`
+# script from the second which we place inside.
+if [ "$QEMU" != "" ]; then
+  tmpdir=/tmp/qemu-img-creation
+  mkdir -p $tmpdir
+  if [ ! -f $tmpdir/$QEMU ]; then
+    curl https://people.mozilla.org/~acrichton/libc-test/qemu/$QEMU.gz | \
+      gunzip -d > $tmpdir/$QEMU
+  fi
+
+  # Create a mount a fresh new filesystem image that we'll later pass to QEMU.
+  # This will have a `run.sh` script will which use the artifacts inside to run
+  # on the host.
+  rm -f $tmpdir/libc-test.img
+  dd if=/dev/null of=$tmpdir/libc-test.img bs=1M seek=50
+  mkfs.ext2 -F $tmpdir/libc-test.img
+  rm -rf $tmpdir/mount
+  mkdir $tmpdir/mount
+  mount -t ext2 -o loop $tmpdir/libc-test.img $tmpdir/mount
+
+  # If we have a cross compiler, then we just do the standard rigamarole of
+  # cross-compiling an executable and then the script to run just executes the
+  # binary.
+  #
+  # If we don't have a cross-compiler, however, then we need to do some crazy
+  # acrobatics to get this to work.  Generate all.{c,rs} on the host which will
+  # be compiled inside QEMU. Do this here because compiling syntex_syntax in
+  # QEMU would time out basically everywhere.
+  if [ "$CAN_CROSS" = "1" ]; then
+    cargo build --manifest-path libc-test/Cargo.toml --target $TARGET
+    cp $CARGO_TARGET_DIR/$TARGET/debug/libc-test $tmpdir/mount/
+    echo 'exec $1/libc-test' > $tmpdir/mount/run.sh
+  else
+    rm -rf $tmpdir/generated
+    mkdir -p $tmpdir/generated
+    cargo build --manifest-path libc-test/generate-files/Cargo.toml
+    (cd libc-test && TARGET=$TARGET OUT_DIR=$tmpdir/generated SKIP_COMPILE=1 \
+      $CARGO_TARGET_DIR/debug/generate-files)
+
+    # Copy this folder into the mounted image, the `run.sh` entry point, and
+    # overwrite the standard libc-test Cargo.toml with the overlay one which will
+    # assume the all.{c,rs} test files have already been generated
+    mkdir $tmpdir/mount/libc
+    cp -r Cargo.* libc-test src ci $tmpdir/mount/libc/
+    ln -s libc-test/target $tmpdir/mount/libc/target
+    cp ci/run-qemu.sh $tmpdir/mount/run.sh
+    echo $TARGET | tee -a $tmpdir/mount/TARGET
+    cp $tmpdir/generated/* $tmpdir/mount/libc/libc-test
+    cp libc-test/run-generated-Cargo.toml $tmpdir/mount/libc/libc-test/Cargo.toml
+  fi
+
+  umount $tmpdir/mount
+
+  # If we can use kvm, prefer that, otherwise just fall back to user-space
+  # emulation.
+  if kvm-ok; then
+    program=kvm
+  else
+    program=qemu-system-x86_64
+  fi
+
+  # Pass -snapshot to prevent tampering with the disk images, this helps when
+  # running this script in development. The two drives are then passed next,
+  # first is the OS and second is the one we just made. Next the network is
+  # configured to work (I'm not entirely sure how), and then finally we turn off
+  # graphics and redirect the serial console output to out.log.
+  $program \
+    -m 1024 \
+    -snapshot \
+    -drive if=virtio,file=$tmpdir/$QEMU \
+    -drive if=virtio,file=$tmpdir/libc-test.img \
+    -net nic,model=virtio \
+    -net user \
+    -nographic \
+    -vga none 2>&1 | tee $CARGO_TARGET_DIR/out.log
+  exec grep "^PASSED .* tests" $CARGO_TARGET_DIR/out.log
+fi
+
 case "$TARGET" in
   *-apple-ios)
     cargo rustc --manifest-path libc-test/Cargo.toml --target $TARGET -- \
@@ -21,26 +104,25 @@ case "$TARGET" in
   arm-linux-androideabi)
     emulator @arm-21 -no-window &
     adb wait-for-device
-    adb push /tmp/$TARGET/debug/libc-test /data/libc-test
+    adb push $CARGO_TARGET_DIR/$TARGET/debug/libc-test /data/libc-test
     adb shell /data/libc-test 2>&1 | tee /tmp/out
     grep "^PASSED .* tests" /tmp/out
     ;;
 
   arm-unknown-linux-gnueabihf)
-    qemu-arm -L /usr/arm-linux-gnueabihf libc-test/target/$TARGET/debug/libc-test
+    qemu-arm -L /usr/arm-linux-gnueabihf $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 
   mips-unknown-linux-gnu)
-    qemu-mips -L /usr/mips-linux-gnu /tmp/$TARGET/debug/libc-test
+    qemu-mips -L /usr/mips-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 
   aarch64-unknown-linux-gnu)
-    qemu-aarch64 -L /usr/aarch64-linux-gnu/ \
-      libc-test/target/$TARGET/debug/libc-test
+    qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 
   *-rumprun-netbsd)
-    rumprun-bake hw_virtio /tmp/libc-test.img /tmp/$TARGET/debug/libc-test
+    rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     qemu-system-x86_64 -nographic -vga none -m 64 \
         -kernel /tmp/libc-test.img 2>&1 | tee /tmp/out &
     sleep 5
@@ -48,6 +130,6 @@ case "$TARGET" in
     ;;
 
   *)
-    libc-test/target/$TARGET/debug/libc-test
+    $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 esac
diff --git a/src/unix/notbsd/linux/mod.rs b/src/unix/notbsd/linux/mod.rs
index a41d09b94f0a7fbe0433557065933dcd1ed38767..bff6c9cd995af6d23c8b06e982896d87fd3589af 100644
--- a/src/unix/notbsd/linux/mod.rs
+++ b/src/unix/notbsd/linux/mod.rs
@@ -479,10 +479,6 @@ f! {
     }
 }
 
-extern {
-    static mut program_invocation_short_name: *mut ::c_char;
-}
-
 extern {
     pub fn shm_open(name: *const c_char, oflag: ::c_int,
                     mode: mode_t) -> ::c_int;