diff --git a/libc-test/Cargo.lock b/Cargo.lock
similarity index 94%
rename from libc-test/Cargo.lock
rename to Cargo.lock
index 32ddec3e80e00b4475eff4ab24160b0f00bd5ed0..6313e804e93182252e949946b9debb390cde2a69 100644
--- a/libc-test/Cargo.lock
+++ b/Cargo.lock
@@ -23,13 +23,14 @@ dependencies = [
 [[package]]
 name = "gcc"
 version = "0.3.35"
-source = "git+https://github.com/alexcrichton/gcc-rs#fbb4ef58f028ee5e61307b479b53c8d8070db52c"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "gcc"
-version = "0.3.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-replace = "gcc 0.3.35 (git+https://github.com/alexcrichton/gcc-rs)"
+name = "generate-files"
+version = "0.1.0"
+dependencies = [
+ "ctest 0.1.0 (git+https://github.com/alexcrichton/ctest)",
+]
 
 [[package]]
 name = "kernel32-sys"
@@ -99,7 +100,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [metadata]
 "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
 "checksum ctest 0.1.0 (git+https://github.com/alexcrichton/ctest)" = "<none>"
-"checksum gcc 0.3.35 (git+https://github.com/alexcrichton/gcc-rs)" = "<none>"
 "checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
diff --git a/Cargo.toml b/Cargo.toml
index a863aa6b05e3323a68ed226698260ae617afda21..5dc0ec4e4e7a0a8d520bcede61dd22ea0beaeef4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,3 +16,6 @@ other common platform libraries.
 [features]
 default = ["use_std"]
 use_std = []
+
+[workspace]
+members = ["libc-test", "libc-test/generate-files"]
diff --git a/appveyor.yml b/appveyor.yml
index de43884265baa0ee4b013365d0b2b17a0e05c849..d52efad43d583c81d8ce2979032f204f02d77d29 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -19,3 +19,7 @@ build: false
 test_script:
   - cargo test
   - cargo run --manifest-path libc-test/Cargo.toml
+
+cache:
+  - target
+  - C:\Users\appveyor\.cargo\registry
diff --git a/ci/docker/i686-unknown-linux-musl/Dockerfile b/ci/docker/i686-unknown-linux-musl/Dockerfile
index b85a75c4a1509ec27f6402f85b0ec3dead192308..87459a1672bdc4921ed26d7f5000b34bf3fe2765 100644
--- a/ci/docker/i686-unknown-linux-musl/Dockerfile
+++ b/ci/docker/i686-unknown-linux-musl/Dockerfile
@@ -18,4 +18,5 @@ RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \
     make CROSS_COMPILE= install -j4 && \
     cd .. && \
     rm -rf musl-1.1.15
-ENV PATH=$PATH:/musl-i686/bin:/rust/bin
+ENV PATH=$PATH:/musl-i686/bin:/rust/bin \
+    CC_i686_unknown_linux_musl=musl-gcc
diff --git a/ci/docker/x86_64-unknown-freebsd/Dockerfile b/ci/docker/x86_64-unknown-freebsd/Dockerfile
index 23135e8d86802535fabde897a4b5ec73c952ab88..b1273382223637a3e8ccf25cafaf34faef71e822 100644
--- a/ci/docker/x86_64-unknown-freebsd/Dockerfile
+++ b/ci/docker/x86_64-unknown-freebsd/Dockerfile
@@ -3,7 +3,7 @@ USER root
 
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
-  qemu qemu-kvm kmod cpu-checker
+  qemu genext2fs
 
 ENTRYPOINT ["sh"]
 
diff --git a/ci/docker/x86_64-unknown-openbsd/Dockerfile b/ci/docker/x86_64-unknown-openbsd/Dockerfile
index 1eea02e9dfa60f7833f1f6068c828517b1304f2a..26340a5ed1ecaa71ce390850f8a22c09e6c1c686 100644
--- a/ci/docker/x86_64-unknown-openbsd/Dockerfile
+++ b/ci/docker/x86_64-unknown-openbsd/Dockerfile
@@ -2,6 +2,7 @@ FROM ubuntu:16.10
 
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
-  gcc libc6-dev qemu qemu-kvm curl ca-certificates kmod cpu-checker
+  gcc libc6-dev qemu curl ca-certificates \
+  genext2fs
 ENV PATH=$PATH:/rust/bin \
     QEMU=2016-09-07/openbsd-6.0-without-pkgs.qcow2
diff --git a/ci/run-docker.sh b/ci/run-docker.sh
index 5ad90652f0d869727d93342afaf5c4047f7c2b1e..e34e65ffcdc0cd5ce8cb77d356d96325a1977b9c 100644
--- a/ci/run-docker.sh
+++ b/ci/run-docker.sh
@@ -7,6 +7,7 @@ run() {
     echo $1
     docker build -t libc ci/docker/$1
     docker run \
+      --rm \
       -v `rustc --print sysroot`:/rust:ro \
       -v `pwd`:/checkout:ro \
       -e CARGO_TARGET_DIR=/tmp/target \
diff --git a/ci/run.sh b/ci/run.sh
index 238a5e57bc34ddb418fb7f62721fb1b99bf8daa5..760353bf57d0a819d4997245d81c15506f815715 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -37,11 +37,7 @@ if [ "$QEMU" != "" ]; then
   # 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
@@ -74,22 +70,18 @@ if [ "$QEMU" != "" ]; then
     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
+  du -sh $tmpdir/mount
+  genext2fs \
+      --root $tmpdir/mount \
+      --size-in-blocks 100000 \
+      $tmpdir/libc-test.img
 
   # 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 \
+  qemu-system-x86_64 \
     -m 1024 \
     -snapshot \
     -drive if=virtio,file=$tmpdir/$qemufile \
diff --git a/libc-test/generate-files/Cargo.lock b/libc-test/generate-files/Cargo.lock
deleted file mode 100644
index 545afc2efb95200feba64e59924edee09886962d..0000000000000000000000000000000000000000
--- a/libc-test/generate-files/Cargo.lock
+++ /dev/null
@@ -1,123 +0,0 @@
-[root]
-name = "generate-files"
-version = "0.1.0"
-dependencies = [
- "ctest 0.1.0 (git+https://github.com/alexcrichton/ctest)",
-]
-
-[[package]]
-name = "advapi32-sys"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "bitflags"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "ctest"
-version = "0.1.0"
-source = "git+https://github.com/alexcrichton/ctest#a6becb6d7fd23d9863cba86eac31d1ffc4082734"
-dependencies = [
- "gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntex_syntax 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "gcc"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "kernel32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "libc"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "libc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "log"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rustc-serialize"
-version = "0.3.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "syntex_syntax"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "term"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "unicode-xid"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
-"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
-"checksum ctest 0.1.0 (git+https://github.com/alexcrichton/ctest)" = "<none>"
-"checksum gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ca10e3e1f1c8278047da19b94dc17c4397861150d5fbcea052eedb1d9847d356"
-"checksum kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b5e7edf375e6d26243bde172f1d5ed1446f4a766fc9b7006e1fd27258243f1"
-"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
-"checksum libc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b3222582df17067e4ffcc6dc12f7f65b5aef89586ef486af1cf97290f7f809fb"
-"checksum log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "038b5d13189a14e5b6ac384fdb7c691a45ef0885f6d2dddbf422e6c3506b8234"
-"checksum rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1a48546a64cae47d06885e9bccadb99d0547d877a94c5167fa451ea33a484456"
-"checksum syntex_syntax 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8739e1a8b53efe7349917259f8ced15f797c89bf788a86e44f61addc0d1ecf68"
-"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281"
-"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
-"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4"
-"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"