diff --git a/tests/gem_pwrite.c b/tests/gem_pwrite.c
index 1c3d23d..8e24c4b 100644
--- a/tests/gem_pwrite.c
+++ b/tests/gem_pwrite.c
@@ -26,6 +26,7 @@
  */
 
 #include "igt.h"
+#include "igt_vgem.h"
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -79,6 +80,93 @@ static const char *bytes_per_sec(char *buf, double v)
 	return buf;
 }
 
+static void do_write_loop(int fd, const char *name, uint32_t handle,
+			  uint32_t *src, int size, int count)
+{
+	double usecs;
+	char buf[100];
+	const char* bps;
+	struct timeval start, end;
+
+	gettimeofday(&start, NULL);
+	do_gem_write(fd, handle, src, size, count);
+	gettimeofday(&end, NULL);
+	usecs = elapsed(&start, &end, count);
+	bps = bytes_per_sec(buf, size/usecs*1e6);
+	igt_info("Time to %s pwrite %d bytes x %6d:\t%7.3fµs, %s\n",
+		 name, size, count, usecs, bps);
+	fflush(stdout);
+}
+
+static void test_i915_bo(int fd, const char *name, uint32_t handle,
+			 uint32_t *src, int size)
+{
+	unsigned i, count;
+
+	for (count = 1; count <= 1<<17; count <<= 1) {
+		uint32_t *ptr = gem_mmap__cpu(fd, handle, 0, size, PROT_WRITE);
+		gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+		memset(ptr, 0, size);
+		munmap(ptr, size);
+
+		do_write_loop(fd, name, handle, src, size, count);
+
+		ptr = gem_mmap__cpu(fd, handle, 0, size, PROT_READ);
+		gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+		for (i = 0; i < size / 4096; i++)
+			igt_assert_eq(ptr[i * 1024], i);
+	}
+}
+
+struct foreign_bo {
+	int vgem_fd;
+	struct vgem_bo bo;
+	uint32_t handle;
+};
+
+static struct foreign_bo create_foreign_bo(int fd, uint32_t size)
+{
+	struct foreign_bo f_bo;
+
+	f_bo.vgem_fd = drm_open_driver(DRIVER_VGEM);
+
+	f_bo.bo.width = 1024;
+	f_bo.bo.height = size / 4096;
+	f_bo.bo.bpp = 32;
+	f_bo.handle = vgem_create_and_import(f_bo.vgem_fd, &f_bo.bo, fd, NULL);
+	igt_assert_eq(size, f_bo.bo.size);
+
+	return f_bo;
+}
+
+static void destroy_foreign_bo(int fd, struct foreign_bo *f_bo)
+{
+	gem_close(fd, f_bo->handle);
+	gem_close(f_bo->vgem_fd, f_bo->bo.handle);
+	close(f_bo->vgem_fd);
+}
+
+static void test_foreign_bo(int fd, const char *name, struct foreign_bo *f_bo,
+			    uint32_t *src, int size)
+{
+	unsigned i, count;
+
+	for (count = 1; count <= 1<<17; count <<= 1) {
+		uint32_t *ptr = vgem_mmap(f_bo->vgem_fd, &f_bo->bo, PROT_WRITE);
+		memset(ptr, 0, size);
+		munmap(ptr, size);
+
+		do_write_loop(fd, name, f_bo->handle, src, size, count);
+
+		ptr = vgem_mmap(f_bo->vgem_fd, &f_bo->bo, PROT_READ);
+		gem_set_domain(fd, f_bo->handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+		for (i = 0; i < size / 4096; i++)
+			igt_assert_eq(ptr[i * 1024], i);
+	}
+}
+
 #define FORWARD 0x1
 #define BACKWARD 0x2
 #define RANDOM 0x4
@@ -205,16 +293,11 @@ static void test_big_gtt(int fd, int scale, unsigned flags)
 	gem_close(fd, handle);
 }
 
-uint32_t *src, dst;
-int fd;
-
 int main(int argc, char **argv)
 {
+	int fd;
+	uint32_t *src;
 	int object_size = 0;
-	double usecs;
-	const char* bps;
-	char buf[100];
-	int count;
 	const struct {
 		int level;
 		const char *name;
@@ -236,50 +319,56 @@ int main(int argc, char **argv)
 	object_size = (object_size + 3) & -4;
 
 	igt_fixture {
+		unsigned i = 0;
 		fd = drm_open_driver(DRIVER_INTEL);
-
-		dst = gem_create(fd, object_size);
 		src = malloc(object_size);
+		igt_assert(src);
+
+		for (i = 0; i < object_size / 4096; i++)
+			((uint32_t *)src)[i * 1024] = i;
 	}
 
-	igt_subtest("basic") {
-		for (count = 1; count <= 1<<17; count <<= 1) {
-			struct timeval start, end;
-
-			gettimeofday(&start, NULL);
-			do_gem_write(fd, dst, src, object_size, count);
-			gettimeofday(&end, NULL);
-			usecs = elapsed(&start, &end, count);
-			bps = bytes_per_sec(buf, object_size/usecs*1e6);
-			igt_info("Time to pwrite %d bytes x %6d:	%7.3fµs, %s\n",
-				 object_size, count, usecs, bps);
-			fflush(stdout);
+	igt_subtest_group {
+		uint32_t handle;
+		igt_fixture
+			handle = gem_create(fd, object_size);
+
+		igt_subtest("basic")
+			test_i915_bo(fd, "basic", handle, src, object_size);
+
+		for (c = cache; c->level != -1; c++) {
+			igt_subtest(c->name) {
+				gem_set_caching(fd, handle, c->level);
+				test_i915_bo(fd, c->name, handle, src, object_size);
+			}
 		}
+
+		igt_fixture
+			gem_close(fd, handle);
 	}
 
-	for (c = cache; c->level != -1; c++) {
-		igt_subtest(c->name) {
-			gem_set_caching(fd, dst, c->level);
-
-			for (count = 1; count <= 1<<17; count <<= 1) {
-				struct timeval start, end;
-
-				gettimeofday(&start, NULL);
-				do_gem_write(fd, dst, src, object_size, count);
-				gettimeofday(&end, NULL);
-				usecs = elapsed(&start, &end, count);
-				bps = bytes_per_sec(buf, object_size/usecs*1e6);
-				igt_info("Time to %s pwrite %d bytes x %6d:	%7.3fµs, %s\n",
-					 c->name, object_size, count, usecs, bps);
-				fflush(stdout);
+	igt_subtest_group {
+		struct foreign_bo f_bo;
+
+		igt_fixture
+			f_bo = create_foreign_bo(fd, object_size);
+
+		igt_subtest("foreign-bo-basic")
+			test_foreign_bo(fd, "basic", &f_bo, src, object_size);
+
+		for (c = cache; c->level != -1; c++) {
+			igt_subtest_f("foreign-bo-%s", c->name) {
+				gem_set_caching(fd, f_bo.handle, c->level);
+				test_foreign_bo(fd, c->name, &f_bo, src, object_size);
 			}
 		}
+
+		igt_fixture
+			destroy_foreign_bo(fd, &f_bo);
 	}
 
-	igt_fixture {
+	igt_fixture
 		free(src);
-		gem_close(fd, dst);
-	}
 
 	{
 		const struct mode {
