diff --git a/tools/kvm/include/kvm/qcow.h b/tools/kvm/include/kvm/qcow.h
index 4be2597..afd776d 100644
--- a/tools/kvm/include/kvm/qcow.h
+++ b/tools/kvm/include/kvm/qcow.h
@@ -4,9 +4,17 @@
 #include <linux/types.h>
 
 #define QCOW_MAGIC		(('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+
 #define QCOW1_VERSION		1
+#define QCOW2_VERSION		2
+
+#define QCOW1_OFLAG_COMPRESSED	(1LL << 63)
+
+#define QCOW1_OFLAG_MASK	QCOW1_OFLAG_COMPRESSED
 
-#define QCOW_OFLAG_COMPRESSED	(1LL << 63)
+#define QCOW2_OFLAG_COPIED	(1LL << 63)
+#define QCOW2_OFLAG_COMPRESSED	(1LL << 62)
+#define QCOW2_OFLAG_MASK	(QCOW2_OFLAG_COPIED|QCOW2_OFLAG_COMPRESSED)
 
 struct qcow_table {
 	u32			table_size;
@@ -19,7 +27,16 @@ struct qcow {
 	int			fd;
 };
 
-struct qcow1_header {
+struct qcow_header {
+	u64			size; /* in bytes */
+	u64			l1_table_offset;
+	u32			l1_size;
+	u8			cluster_bits;
+	u8			l2_bits;
+	uint64_t		oflag_mask;
+};
+
+struct qcow1_header_disk {
 	u32			magic;
 	u32			version;
 
@@ -36,6 +53,27 @@ struct qcow1_header {
 	u64			l1_table_offset;
 };
 
+struct qcow2_header_disk {
+	u32			magic;
+	u32			version;
+
+	u64			backing_file_offset;
+	u32			backing_file_size;
+
+	u32			cluster_bits;
+	u64			size; /* in bytes */
+	u32			crypt_method;
+
+	u32			l1_size;
+	u64			l1_table_offset;
+
+	u64			refcount_table_offset;
+	u32			refcount_table_clusters;
+
+	u32			nb_snapshots;
+	u64			snapshots_offset;
+};
+
 struct disk_image *qcow_probe(int fd);
 
 #endif /* KVM__QCOW_H */
diff --git a/tools/kvm/qcow.c b/tools/kvm/qcow.c
index 11f6454..6d847d0 100644
--- a/tools/kvm/qcow.c
+++ b/tools/kvm/qcow.c
@@ -17,28 +17,28 @@
 
 static inline u64 get_l1_index(struct qcow *q, u64 offset)
 {
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 
 	return offset >> (header->l2_bits + header->cluster_bits);
 }
 
 static inline u64 get_l2_index(struct qcow *q, u64 offset)
 {
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 
 	return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
 }
 
 static inline u64 get_cluster_offset(struct qcow *q, u64 offset)
 {
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 
 	return offset & ((1 << header->cluster_bits)-1);
 }
 
 static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_len)
 {
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 	struct qcow_table *table  = &q->table;
 	u64 *l2_table = NULL;
 	u64 l2_table_offset;
@@ -64,7 +64,7 @@ static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst
 	if (length > dst_len)
 		length = dst_len;
 
-	l2_table_offset = table->l1_table[l1_idx];
+	l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask;
 	if (!l2_table_offset)
 		goto zero_cluster;
 
@@ -81,7 +81,7 @@ static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst
 	if (l2_idx >= l2_table_size)
 		goto out_error;
 
-	clust_start = be64_to_cpu(l2_table[l2_idx]);
+	clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask;
 	if (!clust_start)
 		goto zero_cluster;
 
@@ -105,7 +105,7 @@ static int qcow1_read_sector(struct disk_image *self, uint64_t sector,
 		void *dst, uint32_t dst_len)
 {
 	struct qcow *q = self->priv;
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 	char *buf = dst;
 	u64 offset;
 	u32 nr_read;
@@ -157,12 +157,11 @@ struct disk_image_operations qcow1_disk_ops = {
 
 static int qcow_read_l1_table(struct qcow *q)
 {
-	struct qcow1_header *header = q->header;
+	struct qcow_header *header = q->header;
 	struct qcow_table *table = &q->table;
 	u64 i;
 
-	table->table_size = header->size / ((1 << header->l2_bits) *
-			(1 << header->cluster_bits));
+	table->table_size	= header->l1_size;
 
 	table->l1_table	= calloc(table->table_size, sizeof(u64));
 	if (!table->l1_table)
@@ -178,25 +177,128 @@ static int qcow_read_l1_table(struct qcow *q)
 	return 0;
 }
 
+static void *qcow2_read_header(int fd)
+{
+	struct qcow2_header_disk f_header;
+	struct qcow_header *header;
+
+	header = malloc(sizeof(struct qcow_header));
+	if (!header)
+		return NULL;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
+		return NULL;
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+	be64_to_cpus(&f_header.backing_file_offset);
+	be32_to_cpus(&f_header.backing_file_size);
+	be32_to_cpus(&f_header.cluster_bits);
+	be64_to_cpus(&f_header.size);
+	be32_to_cpus(&f_header.crypt_method);
+	be32_to_cpus(&f_header.l1_size);
+	be64_to_cpus(&f_header.l1_table_offset);
+	be64_to_cpus(&f_header.refcount_table_offset);
+	be32_to_cpus(&f_header.refcount_table_clusters);
+	be32_to_cpus(&f_header.nb_snapshots);
+	be64_to_cpus(&f_header.snapshots_offset);
+
+	*header		= (struct qcow_header) {
+		.size			= f_header.size,
+		.l1_table_offset	= f_header.l1_table_offset,
+		.l1_size		= f_header.l1_size,
+		.cluster_bits		= f_header.cluster_bits,
+		.l2_bits		= f_header.cluster_bits - 3,
+		.oflag_mask		= QCOW2_OFLAG_MASK,
+	};
+
+	return header;
+}
+
+static struct disk_image *qcow2_probe(int fd)
+{
+	struct qcow *q;
+	struct qcow_header *h;
+	struct disk_image *disk_image;
+
+	q = calloc(1, sizeof(struct qcow));
+	if (!q)
+		goto error;
+
+	q->fd = fd;
+
+	h = q->header = qcow2_read_header(fd);
+	if (!h)
+		goto error;
+
+	if (qcow_read_l1_table(q) < 0)
+		goto error;
+
+	disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops);
+	if (!disk_image)
+		goto error;
+	disk_image->priv = q;
+
+	return disk_image;
+error:
+	if (!q)
+		return NULL;
+
+	free(q->table.l1_table);
+	free(q->header);
+	free(q);
+
+	return NULL;
+}
+
+static bool qcow2_check_image(int fd)
+{
+	struct qcow2_header_disk f_header;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
+		return false;
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+
+	if (f_header.magic != QCOW_MAGIC)
+		return false;
+
+	if (f_header.version != QCOW2_VERSION)
+		return false;
+
+	return true;
+}
+
 static void *qcow1_read_header(int fd)
 {
-	struct qcow1_header *header;
+	struct qcow1_header_disk f_header;
+	struct qcow_header *header;
 
-	header = malloc(sizeof(struct qcow1_header));
+	header = malloc(sizeof(struct qcow_header));
 	if (!header)
 		return NULL;
 
-	if (pread_in_full(fd, header, sizeof(struct qcow1_header), 0) < 0)
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
 		return NULL;
 
-	be32_to_cpus(&header->magic);
-	be32_to_cpus(&header->version);
-	be64_to_cpus(&header->backing_file_offset);
-	be32_to_cpus(&header->backing_file_size);
-	be32_to_cpus(&header->mtime);
-	be64_to_cpus(&header->size);
-	be32_to_cpus(&header->crypt_method);
-	be64_to_cpus(&header->l1_table_offset);
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+	be64_to_cpus(&f_header.backing_file_offset);
+	be32_to_cpus(&f_header.backing_file_size);
+	be32_to_cpus(&f_header.mtime);
+	be64_to_cpus(&f_header.size);
+	be32_to_cpus(&f_header.crypt_method);
+	be64_to_cpus(&f_header.l1_table_offset);
+
+	*header		= (struct qcow_header) {
+		.size			= f_header.size,
+		.l1_table_offset	= f_header.l1_table_offset,
+		.l1_size		= f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
+		.cluster_bits		= f_header.cluster_bits,
+		.l2_bits		= f_header.l2_bits,
+		.oflag_mask		= QCOW1_OFLAG_MASK,
+	};
 
 	return header;
 }
@@ -204,7 +306,7 @@ static void *qcow1_read_header(int fd)
 static struct disk_image *qcow1_probe(int fd)
 {
 	struct qcow *q;
-	struct qcow1_header *h;
+	struct qcow_header *h;
 	struct disk_image *disk_image;
 
 	q = calloc(1, sizeof(struct qcow));
@@ -237,29 +339,32 @@ error:
 	return NULL;
 }
 
-static int qcow_check_image(int fd)
+static bool qcow1_check_image(int fd)
 {
-	struct qcow1_header header;
+	struct qcow1_header_disk f_header;
 
-	if (pread_in_full(fd, &header, sizeof(struct qcow1_header), 0) < 0)
-		return -1;
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
+		return false;
 
-	be32_to_cpus(&header.magic);
-	be32_to_cpus(&header.version);
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
 
-	if (header.magic != QCOW_MAGIC)
-		return -1;
+	if (f_header.magic != QCOW_MAGIC)
+		return false;
 
-	if (header.version != QCOW1_VERSION)
-		return -1;
+	if (f_header.version != QCOW1_VERSION)
+		return false;
 
-	return 0;
+	return true;
 }
 
 struct disk_image *qcow_probe(int fd)
 {
-	if (qcow_check_image(fd) < 0)
-		return NULL;
+	if (qcow1_check_image(fd))
+		return qcow1_probe(fd);
+
+	if (qcow2_check_image(fd))
+		return qcow2_probe(fd);
 
-	return qcow1_probe(fd);
+	return NULL;
 }
