diff --git a/SOURCES/kvm-cirrus-add-option-to-disable-blitter.patch b/SOURCES/kvm-cirrus-add-option-to-disable-blitter.patch
new file mode 100644
index 0000000..47d8984
--- /dev/null
+++ b/SOURCES/kvm-cirrus-add-option-to-disable-blitter.patch
@@ -0,0 +1,84 @@
+From 319f3876fafc35412bbf0ef6797c6764c95af6f3 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:03 +0100
+Subject: [PATCH 3/7] cirrus: add option to disable blitter
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-4-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74424
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 3/7] cirrus: add option to disable blitter
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Ok, we have this beast in the cirrus code which is not used at all by
+modern guests, except when you try to find security holes in qemu.  So,
+add an option to disable blitter altogether.  Guests released within
+the last ten years should not show any rendering issues if you turn off
+blitter support.
+
+There are no known bugs in the cirrus blitter code.  But in the past we
+hoped a few times already that we've finally nailed the last issue.  So
+having some easy way to mitigate in case yet another blitter issue shows
+up certainly makes me sleep a bit better at night.
+
+For completeness:  The by far better way to mitigate is to switch away
+from cirrus and use stdvga instead.  Or something more modern like
+virtio-vga in case your guest has support for it.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1489494540-15745-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit 827bd5172641f2a360ff9a3bad57bcf82e7f03f0)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/display/cirrus_vga.c
+---
+ hw/display/cirrus_vga.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 83cef70..86b4c8b 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -203,6 +203,7 @@ typedef struct CirrusVGAState {
+     uint8_t cirrus_hidden_palette[48];
+     uint32_t hw_cursor_x;
+     uint32_t hw_cursor_y;
++    bool enable_blitter;
+     int cirrus_blt_pixelwidth;
+     int cirrus_blt_width;
+     int cirrus_blt_height;
+@@ -954,6 +955,10 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
+ {
+     uint8_t blt_rop;
+ 
++    if (!s->enable_blitter) {
++        goto bitblt_ignore;
++    }
++
+     s->vga.gr[0x31] |= CIRRUS_BLT_BUSY;
+ 
+     s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1;
+@@ -2995,6 +3000,8 @@ static int vga_initfn(ISADevice *dev)
+ static Property isa_cirrus_vga_properties[] = {
+     DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState,
+                        cirrus_vga.vga.vram_size_mb, 16),
++    DEFINE_PROP_BOOL("blitter", struct ISACirrusVGAState,
++                       cirrus_vga.enable_blitter, true),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -3060,6 +3067,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
+ static Property pci_vga_cirrus_properties[] = {
+     DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
+                        cirrus_vga.vga.vram_size_mb, 16),
++    DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState,
++                     cirrus_vga.enable_blitter, true),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cirrus-fix-cirrus_invalidate_region.patch b/SOURCES/kvm-cirrus-fix-cirrus_invalidate_region.patch
new file mode 100644
index 0000000..b180965
--- /dev/null
+++ b/SOURCES/kvm-cirrus-fix-cirrus_invalidate_region.patch
@@ -0,0 +1,51 @@
+From 6c17f6355cac0bc40bae876acf4d31e32978991f Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:04 +0100
+Subject: [PATCH 4/7] cirrus: fix cirrus_invalidate_region
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-5-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74423
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 4/7] cirrus: fix cirrus_invalidate_region
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+off_cur_end is exclusive, so off_cur_end == cirrus_addr_mask is valid.
+Fix calculation to make sure to allow that, otherwise the assert added
+by commit f153b563f8cf121aebf5a2fff5f0110faf58ccb3 can trigger for valid
+blits.
+
+Test case: boot windows nt 4.0
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1489579606-26020-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit e048dac616748273c2153490e9fdf1da242f0cad)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/cirrus_vga.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 86b4c8b..aab6e02 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -661,11 +661,11 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
+     }
+ 
+     for (y = 0; y < lines; y++) {
+-	off_cur = off_begin;
+-	off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
++        off_cur = off_begin;
++        off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1;
+         assert(off_cur_end >= off_cur);
+         memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
+-	off_begin += off_pitch;
++        off_begin += off_pitch;
+     }
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch b/SOURCES/kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
new file mode 100644
index 0000000..6188818
--- /dev/null
+++ b/SOURCES/kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
@@ -0,0 +1,49 @@
+From 8c2a803f9ba8b4293c207917a2acfcfac0548d24 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:07 +0100
+Subject: [PATCH 7/7] cirrus: fix off-by-one in
+ cirrus_bitblt_rop_bkwd_transp_*_16
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-8-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74422
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 7/7] cirrus: fix off-by-one in cirrus_bitblt_rop_bkwd_transp_*_16
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+The switch from pointers to addresses (commit
+026aeffcb4752054830ba203020ed6eb05bcaba8 and
+ffaf857778286ca54e3804432a2369a279e73aa7) added
+a off-by-one bug to 16bit backward blits.  Fix.
+
+Reported-by: 李强 <liqiang6-s@360.cn>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Reviewed-by: Li Qiang <liqiang6-s@360.cn>
+Message-id: 1489735296-19047-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit f019722cbbb45aea153294fc8921fcc96a4d3fa2)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/cirrus_vga_rop.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
+index 16dffb8..c1fc070 100644
+--- a/hw/display/cirrus_vga_rop.h
++++ b/hw/display/cirrus_vga_rop.h
+@@ -220,7 +220,7 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+-            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
++            ROP_OP_TR_16(s, dstaddr - 1, cirrus_src16(s, srcaddr - 1), transp);
+             dstaddr -= 2;
+             srcaddr -= 2;
+         }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch b/SOURCES/kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch
new file mode 100644
index 0000000..2425a76
--- /dev/null
+++ b/SOURCES/kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch
@@ -0,0 +1,630 @@
+From c4928f394f862c78024f4dccb6ea1398dc743c49 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:05 +0100
+Subject: [PATCH 5/7] cirrus: stop passing around dst pointers in the blitter
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-6-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74421
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 5/7] cirrus: stop passing around dst pointers in the blitter
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Instead pass around the address (aka offset into vga memory).  Calculate
+the pointer in the rop_* functions, after applying the mask to the
+address, to make sure the address stays within the valid range.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1489574872-8679-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit 026aeffcb4752054830ba203020ed6eb05bcaba8)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/cirrus_vga.c      |  20 +++---
+ hw/display/cirrus_vga_rop.h  | 161 +++++++++++++++++++++++++------------------
+ hw/display/cirrus_vga_rop2.h |  97 +++++++++++++-------------
+ 3 files changed, 153 insertions(+), 125 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index aab6e02..003cc4c 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -174,11 +174,12 @@
+ 
+ struct CirrusVGAState;
+ typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+-                                     uint8_t * dst, const uint8_t * src,
++                                     uint32_t dstaddr, const uint8_t *src,
+ 				     int dstpitch, int srcpitch,
+ 				     int bltwidth, int bltheight);
+ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
+-                              uint8_t *dst, int dst_pitch, int width, int height);
++                              uint32_t dstaddr, int dst_pitch,
++                              int width, int height);
+ 
+ typedef struct CirrusVGAState {
+     VGACommonState vga;
+@@ -315,14 +316,14 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
+ }
+ 
+ static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
+-                                  uint8_t *dst,const uint8_t *src,
++                                  uint32_t dstaddr, const uint8_t *src,
+                                   int dstpitch,int srcpitch,
+                                   int bltwidth,int bltheight)
+ {
+ }
+ 
+ static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
+-                                   uint8_t *dst,
++                                   uint32_t dstaddr,
+                                    int dstpitch, int bltwidth,int bltheight)
+ {
+ }
+@@ -672,11 +673,8 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
+ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
+ {
+     uint32_t patternsize;
+-    uint8_t *dst;
+     uint8_t *src;
+ 
+-    dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr;
+-
+     if (videosrc) {
+         switch (s->vga.get_bpp(&s->vga)) {
+         case 8:
+@@ -705,7 +703,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
+         return 0;
+     }
+ 
+-    (*s->cirrus_rop) (s, dst, src,
++    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src,
+                       s->cirrus_blt_dstpitch, 0,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+@@ -724,7 +722,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
+         return 0;
+     }
+     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+-    rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
++    rop_func(s, s->cirrus_blt_dstaddr,
+              s->cirrus_blt_dstpitch,
+              s->cirrus_blt_width, s->cirrus_blt_height);
+     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+@@ -791,7 +789,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+         }
+     }
+ 
+-    (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
++    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
+                       s->vga.vram_ptr + s->cirrus_blt_srcaddr,
+ 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 		      s->cirrus_blt_width, s->cirrus_blt_height);
+@@ -842,7 +840,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
+         } else {
+             /* at least one scan line */
+             do {
+-                (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
++                (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
+                                   s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+                 cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
+                                          s->cirrus_blt_width, 1);
+diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
+index a4f96c6..3b16d70 100644
+--- a/hw/display/cirrus_vga_rop.h
++++ b/hw/display/cirrus_vga_rop.h
+@@ -22,31 +22,65 @@
+  * THE SOFTWARE.
+  */
+ 
+-static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src)
++static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s,
++                                          uint32_t dstaddr, uint8_t src)
+ {
++    uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
+     *dst = ROP_FN(*dst, src);
+ }
+ 
+-static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src)
++static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s,
++                                             uint32_t dstaddr, uint8_t src,
++                                             uint8_t transp)
+ {
++    uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
++    uint8_t pixel = ROP_FN(*dst, src);
++    if (pixel != transp) {
++        *dst = pixel;
++    }
++}
++
++static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s,
++                                           uint32_t dstaddr, uint16_t src)
++{
++    uint16_t *dst = (uint16_t *)
++        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
+     *dst = ROP_FN(*dst, src);
+ }
+ 
+-static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src)
++static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s,
++                                              uint32_t dstaddr, uint16_t src,
++                                              uint16_t transp)
++{
++    uint16_t *dst = (uint16_t *)
++        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
++    uint16_t pixel = ROP_FN(*dst, src);
++    if (pixel != transp) {
++        *dst = pixel;
++    }
++}
++
++static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s,
++                                           uint32_t dstaddr, uint32_t src)
+ {
++    uint32_t *dst = (uint32_t *)
++        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]);
+     *dst = ROP_FN(*dst, src);
+ }
+ 
+-#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s)
+-#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s)
+-#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s)
++#define ROP_OP(st, d, s)           glue(rop_8_, ROP_NAME)(st, d, s)
++#define ROP_OP_TR(st, d, s, t)     glue(rop_tr_8_, ROP_NAME)(st, d, s, t)
++#define ROP_OP_16(st, d, s)        glue(rop_16_, ROP_NAME)(st, d, s)
++#define ROP_OP_TR_16(st, d, s, t)  glue(rop_tr_16_, ROP_NAME)(st, d, s, t)
++#define ROP_OP_32(st, d, s)        glue(rop_32_, ROP_NAME)(st, d, s)
+ #undef ROP_FN
+ 
+ static void
+ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
+-                             uint8_t *dst,const uint8_t *src,
+-                             int dstpitch,int srcpitch,
+-                             int bltwidth,int bltheight)
++                                       uint32_t dstaddr,
++                                       const uint8_t *src,
++                                       int dstpitch, int srcpitch,
++                                       int bltwidth, int bltheight)
+ {
+     int x,y;
+     dstpitch -= bltwidth;
+@@ -59,43 +93,47 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP(dst, *src);
+-            dst++;
++            ROP_OP(s, dstaddr, *src);
++            dstaddr++;
+             src++;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
+-                                        uint8_t *dst,const uint8_t *src,
+-                                        int dstpitch,int srcpitch,
+-                                        int bltwidth,int bltheight)
++                                        uint32_t dstaddr,
++                                        const uint8_t *src,
++                                        int dstpitch, int srcpitch,
++                                        int bltwidth, int bltheight)
+ {
+     int x,y;
+     dstpitch += bltwidth;
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP(dst, *src);
+-            dst--;
++            ROP_OP(s, dstaddr, *src);
++            dstaddr--;
+             src--;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+-						       uint8_t *dst,const uint8_t *src,
+-						       int dstpitch,int srcpitch,
+-						       int bltwidth,int bltheight)
++                                                       uint32_t dstaddr,
++                                                       const uint8_t *src,
++                                                       int dstpitch,
++                                                       int srcpitch,
++                                                       int bltwidth,
++                                                       int bltheight)
+ {
+     int x,y;
+-    uint8_t p;
++    uint8_t transp = s->vga.gr[0x34];
+     dstpitch -= bltwidth;
+     srcpitch -= bltwidth;
+ 
+@@ -105,48 +143,50 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-	    p = *dst;
+-            ROP_OP(&p, *src);
+-	    if (p != s->vga.gr[0x34]) *dst = p;
+-            dst++;
++            ROP_OP_TR(s, dstaddr, *src, transp);
++            dstaddr++;
+             src++;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+-							uint8_t *dst,const uint8_t *src,
+-							int dstpitch,int srcpitch,
+-							int bltwidth,int bltheight)
++                                                        uint32_t dstaddr,
++                                                        const uint8_t *src,
++                                                        int dstpitch,
++                                                        int srcpitch,
++                                                        int bltwidth,
++                                                        int bltheight)
+ {
+     int x,y;
+-    uint8_t p;
++    uint8_t transp = s->vga.gr[0x34];
+     dstpitch += bltwidth;
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-	    p = *dst;
+-            ROP_OP(&p, *src);
+-	    if (p != s->vga.gr[0x34]) *dst = p;
+-            dst--;
++            ROP_OP_TR(s, dstaddr, *src, transp);
++            dstaddr--;
+             src--;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+-							uint8_t *dst,const uint8_t *src,
+-							int dstpitch,int srcpitch,
+-							int bltwidth,int bltheight)
++                                                        uint32_t dstaddr,
++                                                        const uint8_t *src,
++                                                        int dstpitch,
++                                                        int srcpitch,
++                                                        int bltwidth,
++                                                        int bltheight)
+ {
+     int x,y;
+-    uint8_t p1, p2;
++    uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
+     dstpitch -= bltwidth;
+     srcpitch -= bltwidth;
+ 
+@@ -156,46 +196,35 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+-	    p1 = *dst;
+-	    p2 = *(dst+1);
+-            ROP_OP(&p1, *src);
+-            ROP_OP(&p2, *(src + 1));
+-	    if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
+-		*dst = p1;
+-		*(dst+1) = p2;
+-	    }
+-            dst+=2;
+-            src+=2;
++            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
++            dstaddr += 2;
++            src += 2;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+-							 uint8_t *dst,const uint8_t *src,
+-							 int dstpitch,int srcpitch,
+-							 int bltwidth,int bltheight)
++                                                         uint32_t dstaddr,
++                                                         const uint8_t *src,
++                                                         int dstpitch,
++                                                         int srcpitch,
++                                                         int bltwidth,
++                                                         int bltheight)
+ {
+     int x,y;
+-    uint8_t p1, p2;
++    uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
+     dstpitch += bltwidth;
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+-	    p1 = *(dst-1);
+-	    p2 = *dst;
+-            ROP_OP(&p1, *(src - 1));
+-            ROP_OP(&p2, *src);
+-	    if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
+-		*(dst-1) = p1;
+-		*dst = p2;
+-	    }
+-            dst-=2;
+-            src-=2;
++            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
++            dstaddr -= 2;
++            src -= 2;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+         src += srcpitch;
+     }
+ }
+diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
+index d28bcc6..bc92f0e 100644
+--- a/hw/display/cirrus_vga_rop2.h
++++ b/hw/display/cirrus_vga_rop2.h
+@@ -23,27 +23,29 @@
+  */
+ 
+ #if DEPTH == 8
+-#define PUTPIXEL()    ROP_OP(&d[0], col)
++#define PUTPIXEL(s, a, c)    ROP_OP(s, a, c)
+ #elif DEPTH == 16
+-#define PUTPIXEL()    ROP_OP_16((uint16_t *)&d[0], col)
++#define PUTPIXEL(s, a, c)    ROP_OP_16(s, a, c)
+ #elif DEPTH == 24
+-#define PUTPIXEL()    ROP_OP(&d[0], col);        \
+-                      ROP_OP(&d[1], (col >> 8)); \
+-                      ROP_OP(&d[2], (col >> 16))
++#define PUTPIXEL(s, a, c)    do {          \
++        ROP_OP(s, a,     c);               \
++        ROP_OP(s, a + 1, (col >> 8));      \
++        ROP_OP(s, a + 2, (col >> 16));     \
++    } while (0)
+ #elif DEPTH == 32
+-#define PUTPIXEL()    ROP_OP_32(((uint32_t *)&d[0]), col)
++#define PUTPIXEL(s, a, c)    ROP_OP_32(s, a, c)
+ #else
+ #error unsupported DEPTH
+ #endif
+ 
+ static void
+ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+-     (CirrusVGAState * s, uint8_t * dst,
+-      const uint8_t * src,
++     (CirrusVGAState *s, uint32_t dstaddr,
++      const uint8_t *src,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+-    uint8_t *d;
++    uint32_t addr;
+     int x, y, pattern_y, pattern_pitch, pattern_x;
+     unsigned int col;
+     const uint8_t *src1;
+@@ -63,7 +65,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+     pattern_y = s->cirrus_blt_srcaddr & 7;
+     for(y = 0; y < bltheight; y++) {
+         pattern_x = skipleft;
+-        d = dst + skipleft;
++        addr = dstaddr + skipleft;
+         src1 = src + pattern_y * pattern_pitch;
+         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
+ #if DEPTH == 8
+@@ -82,23 +84,23 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+             col = ((uint32_t *)(src1 + pattern_x))[0];
+             pattern_x = (pattern_x + 4) & 31;
+ #endif
+-            PUTPIXEL();
+-            d += (DEPTH / 8);
++            PUTPIXEL(s, addr, col);
++            addr += (DEPTH / 8);
+         }
+         pattern_y = (pattern_y + 1) & 7;
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+     }
+ }
+ 
+ /* NOTE: srcpitch is ignored */
+ static void
+ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+-     (CirrusVGAState * s, uint8_t * dst,
+-      const uint8_t * src,
++     (CirrusVGAState *s, uint32_t dstaddr,
++      const uint8_t *src,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+-    uint8_t *d;
++    uint32_t addr;
+     int x, y;
+     unsigned bits, bits_xor;
+     unsigned int col;
+@@ -123,7 +125,7 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+     for(y = 0; y < bltheight; y++) {
+         bitmask = 0x80 >> srcskipleft;
+         bits = *src++ ^ bits_xor;
+-        d = dst + dstskipleft;
++        addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             if ((bitmask & 0xff) == 0) {
+                 bitmask = 0x80;
+@@ -131,24 +133,24 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+             }
+             index = (bits & bitmask);
+             if (index) {
+-                PUTPIXEL();
++                PUTPIXEL(s, addr, col);
+             }
+-            d += (DEPTH / 8);
++            addr += (DEPTH / 8);
+             bitmask >>= 1;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+-     (CirrusVGAState * s, uint8_t * dst,
+-      const uint8_t * src,
++     (CirrusVGAState *s, uint32_t dstaddr,
++      const uint8_t *src,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+     uint32_t colors[2];
+-    uint8_t *d;
++    uint32_t addr;
+     int x, y;
+     unsigned bits;
+     unsigned int col;
+@@ -161,29 +163,29 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+     for(y = 0; y < bltheight; y++) {
+         bitmask = 0x80 >> srcskipleft;
+         bits = *src++;
+-        d = dst + dstskipleft;
++        addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             if ((bitmask & 0xff) == 0) {
+                 bitmask = 0x80;
+                 bits = *src++;
+             }
+             col = colors[!!(bits & bitmask)];
+-            PUTPIXEL();
+-            d += (DEPTH / 8);
++            PUTPIXEL(s, addr, col);
++            addr += (DEPTH / 8);
+             bitmask >>= 1;
+         }
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+-     (CirrusVGAState * s, uint8_t * dst,
+-      const uint8_t * src,
++     (CirrusVGAState *s, uint32_t dstaddr,
++      const uint8_t *src,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+-    uint8_t *d;
++    uint32_t addr;
+     int x, y, bitpos, pattern_y;
+     unsigned int bits, bits_xor;
+     unsigned int col;
+@@ -207,28 +209,28 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+     for(y = 0; y < bltheight; y++) {
+         bits = src[pattern_y] ^ bits_xor;
+         bitpos = 7 - srcskipleft;
+-        d = dst + dstskipleft;
++        addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             if ((bits >> bitpos) & 1) {
+-                PUTPIXEL();
++                PUTPIXEL(s, addr, col);
+             }
+-            d += (DEPTH / 8);
++            addr += (DEPTH / 8);
+             bitpos = (bitpos - 1) & 7;
+         }
+         pattern_y = (pattern_y + 1) & 7;
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
+-     (CirrusVGAState * s, uint8_t * dst,
+-      const uint8_t * src,
++     (CirrusVGAState *s, uint32_t dstaddr,
++      const uint8_t *src,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+     uint32_t colors[2];
+-    uint8_t *d;
++    uint32_t addr;
+     int x, y, bitpos, pattern_y;
+     unsigned int bits;
+     unsigned int col;
+@@ -242,38 +244,37 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
+     for(y = 0; y < bltheight; y++) {
+         bits = src[pattern_y];
+         bitpos = 7 - srcskipleft;
+-        d = dst + dstskipleft;
++        addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             col = colors[(bits >> bitpos) & 1];
+-            PUTPIXEL();
+-            d += (DEPTH / 8);
++            PUTPIXEL(s, addr, col);
++            addr += (DEPTH / 8);
+             bitpos = (bitpos - 1) & 7;
+         }
+         pattern_y = (pattern_y + 1) & 7;
+-        dst += dstpitch;
++        dstaddr += dstpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s,
+-      uint8_t *dst, int dst_pitch,
++      uint32_t dstaddr, int dst_pitch,
+       int width, int height)
+ {
+-    uint8_t *d, *d1;
++    uint32_t addr;
+     uint32_t col;
+     int x, y;
+ 
+     col = s->cirrus_blt_fgcol;
+ 
+-    d1 = dst;
+     for(y = 0; y < height; y++) {
+-        d = d1;
++        addr = dstaddr;
+         for(x = 0; x < width; x += (DEPTH / 8)) {
+-            PUTPIXEL();
+-            d += (DEPTH / 8);
++            PUTPIXEL(s, addr, col);
++            addr += (DEPTH / 8);
+         }
+-        d1 += dst_pitch;
++        dstaddr += dst_pitch;
+     }
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch b/SOURCES/kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
new file mode 100644
index 0000000..29837cc
--- /dev/null
+++ b/SOURCES/kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
@@ -0,0 +1,455 @@
+From d29af2a00b6126d2c3af535d128beeb80216c197 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:06 +0100
+Subject: [PATCH 6/7] cirrus: stop passing around src pointers in the blitter
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-7-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74417
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 6/7] cirrus: stop passing around src pointers in the blitter
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Does basically the same as "cirrus: stop passing around dst pointers in
+the blitter", just for the src pointer instead of the dst pointer.
+
+For the src we have to care about cputovideo blits though and fetch the
+data from s->cirrus_bltbuf instead of vga memory.  The cirrus_src*()
+helper functions handle that.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1489584487-3489-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit ffaf857778286ca54e3804432a2369a279e73aa7)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/cirrus_vga.c      | 61 +++++++++++++++++++++++++++++++++++---------
+ hw/display/cirrus_vga_rop.h  | 48 +++++++++++++++++-----------------
+ hw/display/cirrus_vga_rop2.h | 38 ++++++++++++++-------------
+ 3 files changed, 93 insertions(+), 54 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 003cc4c..c1324ab 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -174,7 +174,7 @@
+ 
+ struct CirrusVGAState;
+ typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+-                                     uint32_t dstaddr, const uint8_t *src,
++                                     uint32_t dstaddr, uint32_t srcaddr,
+ 				     int dstpitch, int srcpitch,
+ 				     int bltwidth, int bltheight);
+ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
+@@ -316,7 +316,7 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
+ }
+ 
+ static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
+-                                  uint32_t dstaddr, const uint8_t *src,
++                                  uint32_t dstaddr, uint32_t srcaddr,
+                                   int dstpitch,int srcpitch,
+                                   int bltwidth,int bltheight)
+ {
+@@ -328,6 +328,45 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
+ {
+ }
+ 
++static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr)
++{
++    if (s->cirrus_srccounter) {
++        /* cputovideo */
++        return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)];
++    } else {
++        /* videotovideo */
++        return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask];
++    }
++}
++
++static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr)
++{
++    uint16_t *src;
++
++    if (s->cirrus_srccounter) {
++        /* cputovideo */
++        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1];
++    } else {
++        /* videotovideo */
++        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1];
++    }
++    return *src;
++}
++
++static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr)
++{
++    uint32_t *src;
++
++    if (s->cirrus_srccounter) {
++        /* cputovideo */
++        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3];
++    } else {
++        /* videotovideo */
++        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3];
++    }
++    return *src;
++}
++
+ #define ROP_NAME 0
+ #define ROP_FN(d, s) 0
+ #include "cirrus_vga_rop.h"
+@@ -670,10 +709,10 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
+     }
+ }
+ 
+-static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
++static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s)
+ {
+     uint32_t patternsize;
+-    uint8_t *src;
++    bool videosrc = !s->cirrus_srccounter;
+ 
+     if (videosrc) {
+         switch (s->vga.get_bpp(&s->vga)) {
+@@ -694,16 +733,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
+         if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
+             return 0;
+         }
+-        src = s->vga.vram_ptr + s->cirrus_blt_srcaddr;
+-    } else {
+-        src = s->cirrus_bltbuf;
+     }
+ 
+     if (blit_is_unsafe(s, true)) {
+         return 0;
+     }
+ 
+-    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src,
++    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
++                      videosrc ? s->cirrus_blt_srcaddr : 0,
+                       s->cirrus_blt_dstpitch, 0,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+@@ -740,7 +777,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
+ 
+ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
+ {
+-    return cirrus_bitblt_common_patterncopy(s, true);
++    return cirrus_bitblt_common_patterncopy(s);
+ }
+ 
+ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+@@ -790,7 +827,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+     }
+ 
+     (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
+-                      s->vga.vram_ptr + s->cirrus_blt_srcaddr,
++                      s->cirrus_blt_srcaddr,
+ 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 		      s->cirrus_blt_width, s->cirrus_blt_height);
+ 
+@@ -833,7 +870,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
+ 
+     if (s->cirrus_srccounter > 0) {
+         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+-            cirrus_bitblt_common_patterncopy(s, false);
++            cirrus_bitblt_common_patterncopy(s);
+         the_end:
+             s->cirrus_srccounter = 0;
+             cirrus_bitblt_reset(s);
+@@ -841,7 +878,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
+             /* at least one scan line */
+             do {
+                 (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
+-                                  s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
++                                 0, 0, 0, s->cirrus_blt_width, 1);
+                 cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
+                                          s->cirrus_blt_width, 1);
+                 s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
+diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
+index 3b16d70..16dffb8 100644
+--- a/hw/display/cirrus_vga_rop.h
++++ b/hw/display/cirrus_vga_rop.h
+@@ -78,7 +78,7 @@ static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s,
+ static void
+ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
+                                        uint32_t dstaddr,
+-                                       const uint8_t *src,
++                                       uint32_t srcaddr,
+                                        int dstpitch, int srcpitch,
+                                        int bltwidth, int bltheight)
+ {
+@@ -93,19 +93,19 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP(s, dstaddr, *src);
++            ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
+             dstaddr++;
+-            src++;
++            srcaddr++;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
+                                         uint32_t dstaddr,
+-                                        const uint8_t *src,
++                                        uint32_t srcaddr,
+                                         int dstpitch, int srcpitch,
+                                         int bltwidth, int bltheight)
+ {
+@@ -114,19 +114,19 @@ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP(s, dstaddr, *src);
++            ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
+             dstaddr--;
+-            src--;
++            srcaddr--;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+                                                        uint32_t dstaddr,
+-                                                       const uint8_t *src,
++                                                       uint32_t srcaddr,
+                                                        int dstpitch,
+                                                        int srcpitch,
+                                                        int bltwidth,
+@@ -143,19 +143,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP_TR(s, dstaddr, *src, transp);
++            ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
+             dstaddr++;
+-            src++;
++            srcaddr++;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+                                                         uint32_t dstaddr,
+-                                                        const uint8_t *src,
++                                                        uint32_t srcaddr,
+                                                         int dstpitch,
+                                                         int srcpitch,
+                                                         int bltwidth,
+@@ -167,19 +167,19 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+-            ROP_OP_TR(s, dstaddr, *src, transp);
++            ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
+             dstaddr--;
+-            src--;
++            srcaddr--;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+                                                         uint32_t dstaddr,
+-                                                        const uint8_t *src,
++                                                        uint32_t srcaddr,
+                                                         int dstpitch,
+                                                         int srcpitch,
+                                                         int bltwidth,
+@@ -196,19 +196,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+ 
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+-            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
++            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
+             dstaddr += 2;
+-            src += 2;
++            srcaddr += 2;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+ static void
+ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+                                                          uint32_t dstaddr,
+-                                                         const uint8_t *src,
++                                                         uint32_t srcaddr,
+                                                          int dstpitch,
+                                                          int srcpitch,
+                                                          int bltwidth,
+@@ -220,12 +220,12 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+     srcpitch += bltwidth;
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+-            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
++            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
+             dstaddr -= 2;
+-            src -= 2;
++            srcaddr -= 2;
+         }
+         dstaddr += dstpitch;
+-        src += srcpitch;
++        srcaddr += srcpitch;
+     }
+ }
+ 
+diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
+index bc92f0e..b86bcd6 100644
+--- a/hw/display/cirrus_vga_rop2.h
++++ b/hw/display/cirrus_vga_rop2.h
+@@ -41,14 +41,14 @@
+ static void
+ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s, uint32_t dstaddr,
+-      const uint8_t *src,
++      uint32_t srcaddr,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+     uint32_t addr;
+     int x, y, pattern_y, pattern_pitch, pattern_x;
+     unsigned int col;
+-    const uint8_t *src1;
++    uint32_t src1addr;
+ #if DEPTH == 24
+     int skipleft = s->vga.gr[0x2f] & 0x1f;
+ #else
+@@ -66,22 +66,24 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+     for(y = 0; y < bltheight; y++) {
+         pattern_x = skipleft;
+         addr = dstaddr + skipleft;
+-        src1 = src + pattern_y * pattern_pitch;
++        src1addr = srcaddr + pattern_y * pattern_pitch;
+         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
+ #if DEPTH == 8
+-            col = src1[pattern_x];
++            col = cirrus_src(s, src1addr + pattern_x);
+             pattern_x = (pattern_x + 1) & 7;
+ #elif DEPTH == 16
+-            col = ((uint16_t *)(src1 + pattern_x))[0];
++            col = cirrus_src16(s, src1addr + pattern_x);
+             pattern_x = (pattern_x + 2) & 15;
+ #elif DEPTH == 24
+             {
+-                const uint8_t *src2 = src1 + pattern_x * 3;
+-                col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
++                uint32_t src2addr = src1addr + pattern_x * 3;
++                col = cirrus_src(s, src2addr) |
++                    (cirrus_src(s, src2addr + 1) << 8) |
++                    (cirrus_src(s, src2addr + 2) << 16);
+                 pattern_x = (pattern_x + 1) & 7;
+             }
+ #else
+-            col = ((uint32_t *)(src1 + pattern_x))[0];
++            col = cirrus_src32(s, src1addr + pattern_x);
+             pattern_x = (pattern_x + 4) & 31;
+ #endif
+             PUTPIXEL(s, addr, col);
+@@ -96,7 +98,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+ static void
+ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s, uint32_t dstaddr,
+-      const uint8_t *src,
++      uint32_t srcaddr,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+@@ -124,12 +126,12 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+ 
+     for(y = 0; y < bltheight; y++) {
+         bitmask = 0x80 >> srcskipleft;
+-        bits = *src++ ^ bits_xor;
++        bits = cirrus_src(s, srcaddr++) ^ bits_xor;
+         addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             if ((bitmask & 0xff) == 0) {
+                 bitmask = 0x80;
+-                bits = *src++ ^ bits_xor;
++                bits = cirrus_src(s, srcaddr++) ^ bits_xor;
+             }
+             index = (bits & bitmask);
+             if (index) {
+@@ -145,7 +147,7 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+ static void
+ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s, uint32_t dstaddr,
+-      const uint8_t *src,
++      uint32_t srcaddr,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+@@ -162,12 +164,12 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+     colors[1] = s->cirrus_blt_fgcol;
+     for(y = 0; y < bltheight; y++) {
+         bitmask = 0x80 >> srcskipleft;
+-        bits = *src++;
++        bits = cirrus_src(s, srcaddr++);
+         addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+             if ((bitmask & 0xff) == 0) {
+                 bitmask = 0x80;
+-                bits = *src++;
++                bits = cirrus_src(s, srcaddr++);
+             }
+             col = colors[!!(bits & bitmask)];
+             PUTPIXEL(s, addr, col);
+@@ -181,7 +183,7 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+ static void
+ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s, uint32_t dstaddr,
+-      const uint8_t *src,
++      uint32_t srcaddr,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+@@ -207,7 +209,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+     pattern_y = s->cirrus_blt_srcaddr & 7;
+ 
+     for(y = 0; y < bltheight; y++) {
+-        bits = src[pattern_y] ^ bits_xor;
++        bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
+         bitpos = 7 - srcskipleft;
+         addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+@@ -225,7 +227,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+ static void
+ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
+      (CirrusVGAState *s, uint32_t dstaddr,
+-      const uint8_t *src,
++      uint32_t srcaddr,
+       int dstpitch, int srcpitch,
+       int bltwidth, int bltheight)
+ {
+@@ -242,7 +244,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
+     pattern_y = s->cirrus_blt_srcaddr & 7;
+ 
+     for(y = 0; y < bltheight; y++) {
+-        bits = src[pattern_y];
++        bits = cirrus_src(s, srcaddr + pattern_y);
+         bitpos = 7 - srcskipleft;
+         addr = dstaddr + dstskipleft;
+         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch b/SOURCES/kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch
new file mode 100644
index 0000000..854e932
--- /dev/null
+++ b/SOURCES/kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch
@@ -0,0 +1,297 @@
+From de457fc23e747a0c622e0fd23e49893c1f1da460 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:02 +0100
+Subject: [PATCH 2/7] cirrus/vnc: zap bitblit support from console code.
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-3-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74418
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 2/7] cirrus/vnc: zap bitblit support from console code.
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+There is a special code path (dpy_gfx_copy) to allow graphic emulation
+notify user interface code about bitblit operations carryed out by
+guests.  It is supported by cirrus and vnc server.  The intended purpose
+is to optimize display scrolls and just send over the scroll op instead
+of a full display update.
+
+This is rarely used these days though because modern guests simply don't
+use the cirrus blitter any more.  Any linux guest using the cirrus drm
+driver doesn't.  Any windows guest newer than winxp doesn't ship with a
+cirrus driver any more and thus uses the cirrus as simple framebuffer.
+
+So this code tends to bitrot and bugs can go unnoticed for a long time.
+See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
+which fixes a bug lingering in the code for almost a year, added by
+commit "c7628bf vnc: only alloc server surface with clients connected".
+
+Also the vnc server will throttle the frame rate in case it figures the
+network can't keep up (send buffers are full).  This doesn't work with
+dpy_gfx_copy, for any copy operation sent to the vnc client we have to
+send all outstanding updates beforehand, otherwise the vnc client might
+run the client side blit on outdated data and thereby corrupt the
+display.  So this dpy_gfx_copy "optimization" might even make things
+worse on slow network links.
+
+Lets kill it once for all.
+
+Oh, and one more reason: Turns out (after writing the patch) we have a
+security bug in that code path ...
+
+Fixes: CVE-2016-9603
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1489494419-14340-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit 50628d3479e4f9aa97e323506856e394fe7ad7a6)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	include/ui/console.h
+	ui/vnc.c
+---
+ hw/display/cirrus_vga.c | 12 ++-----
+ include/ui/console.h    |  7 ----
+ ui/console.c            | 28 ---------------
+ ui/vnc.c                | 96 -------------------------------------------------
+ 4 files changed, 3 insertions(+), 140 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 1b972db..83cef70 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -790,21 +790,15 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+         }
+     }
+ 
+-    /* we have to flush all pending changes so that the copy
+-       is generated at the appropriate moment in time */
+-    if (notify)
+-        graphic_hw_update(s->vga.con);
+-
+     (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
+                       s->vga.vram_ptr + s->cirrus_blt_srcaddr,
+ 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 		      s->cirrus_blt_width, s->cirrus_blt_height);
+ 
+     if (notify) {
+-        qemu_console_copy(s->vga.con,
+-			  sx, sy, dx, dy,
+-			  s->cirrus_blt_width / depth,
+-			  s->cirrus_blt_height);
++        dpy_gfx_update(s->vga.con, dx, dy,
++                       s->cirrus_blt_width / depth,
++                       s->cirrus_blt_height);
+     }
+ 
+     /* we don't have to notify the display that this portion has
+diff --git a/include/ui/console.h b/include/ui/console.h
+index 4307b5f..7f5fa66 100644
+--- a/include/ui/console.h
++++ b/include/ui/console.h
+@@ -159,9 +159,6 @@ typedef struct DisplayChangeListenerOps {
+                            int x, int y, int w, int h);
+     void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
+                            struct DisplaySurface *new_surface);
+-    void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
+-                         int src_x, int src_y,
+-                         int dst_x, int dst_y, int w, int h);
+ 
+     void (*dpy_text_cursor)(DisplayChangeListener *dcl,
+                             int x, int y);
+@@ -216,8 +213,6 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl);
+ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_gfx_replace_surface(QemuConsole *con,
+                              DisplaySurface *surface);
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+-                  int dst_x, int dst_y, int w, int h);
+ void dpy_text_cursor(QemuConsole *con, int x, int y);
+ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_text_resize(QemuConsole *con, int w, int h);
+@@ -295,8 +290,6 @@ void text_consoles_set_display(DisplayState *ds);
+ void console_select(unsigned int index);
+ void console_color_init(DisplayState *ds);
+ void qemu_console_resize(QemuConsole *con, int width, int height);
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+-                       int dst_x, int dst_y, int w, int h);
+ DisplaySurface *qemu_console_surface(QemuConsole *con);
+ DisplayState *qemu_console_displaystate(QemuConsole *console);
+ 
+diff --git a/ui/console.c b/ui/console.c
+index d422083..fb08ec0 100644
+--- a/ui/console.c
++++ b/ui/console.c
+@@ -1461,27 +1461,6 @@ void dpy_refresh(DisplayState *s)
+     }
+ }
+ 
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+-                  int dst_x, int dst_y, int w, int h)
+-{
+-    DisplayState *s = con->ds;
+-    DisplayChangeListener *dcl;
+-
+-    if (!qemu_console_is_visible(con)) {
+-        return;
+-    }
+-    QLIST_FOREACH(dcl, &s->listeners, next) {
+-        if (con != (dcl->con ? dcl->con : active_console)) {
+-            continue;
+-        }
+-        if (dcl->ops->dpy_gfx_copy) {
+-            dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
+-        } else { /* TODO */
+-            dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+-        }
+-    }
+-}
+-
+ void dpy_text_cursor(QemuConsole *con, int x, int y)
+ {
+     DisplayState *s = con->ds;
+@@ -1843,13 +1822,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
+     dpy_gfx_replace_surface(s, surface);
+ }
+ 
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+-                       int dst_x, int dst_y, int w, int h)
+-{
+-    assert(con->console_type == GRAPHIC_CONSOLE);
+-    dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
+-}
+-
+ DisplaySurface *qemu_console_surface(QemuConsole *console)
+ {
+     return console->surface;
+diff --git a/ui/vnc.c b/ui/vnc.c
+index a0e2d33..c7a7853 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -417,7 +417,6 @@ out_error:
+ */
+ 
+ static int vnc_update_client(VncState *vs, int has_dirty);
+-static int vnc_update_client_sync(VncState *vs, int has_dirty);
+ static void vnc_disconnect_start(VncState *vs);
+ 
+ static void vnc_colordepth(VncState *vs);
+@@ -721,93 +720,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+     return n;
+ }
+ 
+-static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+-{
+-    /* send bitblit op to the vnc client */
+-    vnc_lock_output(vs);
+-    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+-    vnc_write_u8(vs, 0);
+-    vnc_write_u16(vs, 1); /* number of rects */
+-    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
+-    vnc_write_u16(vs, src_x);
+-    vnc_write_u16(vs, src_y);
+-    vnc_unlock_output(vs);
+-    vnc_flush(vs);
+-}
+-
+-static void vnc_dpy_copy(DisplayChangeListener *dcl,
+-                         int src_x, int src_y,
+-                         int dst_x, int dst_y, int w, int h)
+-{
+-    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
+-    VncState *vs, *vn;
+-    uint8_t *src_row;
+-    uint8_t *dst_row;
+-    int i, x, y, pitch, inc, w_lim, s;
+-    int cmp_bytes;
+-
+-    vnc_refresh_server_surface(vd);
+-    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
+-        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+-            vs->force_update = 1;
+-            vnc_update_client_sync(vs, 1);
+-            /* vs might be free()ed here */
+-        }
+-    }
+-
+-    /* do bitblit op on the local surface too */
+-    pitch = vnc_server_fb_stride(vd);
+-    src_row = vnc_server_fb_ptr(vd, src_x, src_y);
+-    dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
+-    y = dst_y;
+-    inc = 1;
+-    if (dst_y > src_y) {
+-        /* copy backwards */
+-        src_row += pitch * (h-1);
+-        dst_row += pitch * (h-1);
+-        pitch = -pitch;
+-        y = dst_y + h - 1;
+-        inc = -1;
+-    }
+-    w_lim = w - (16 - (dst_x % 16));
+-    if (w_lim < 0)
+-        w_lim = w;
+-    else
+-        w_lim = w - (w_lim % 16);
+-    for (i = 0; i < h; i++) {
+-        for (x = 0; x <= w_lim;
+-                x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
+-            if (x == w_lim) {
+-                if ((s = w - w_lim) == 0)
+-                    break;
+-            } else if (!x) {
+-                s = (16 - (dst_x % 16));
+-                s = MIN(s, w_lim);
+-            } else {
+-                s = 16;
+-            }
+-            cmp_bytes = s * VNC_SERVER_FB_BYTES;
+-            if (memcmp(src_row, dst_row, cmp_bytes) == 0)
+-                continue;
+-            memmove(dst_row, src_row, cmp_bytes);
+-            QTAILQ_FOREACH(vs, &vd->clients, next) {
+-                if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+-                    set_bit(((x + dst_x) / 16), vs->dirty[y]);
+-                }
+-            }
+-        }
+-        src_row += pitch - w * VNC_SERVER_FB_BYTES;
+-        dst_row += pitch - w * VNC_SERVER_FB_BYTES;
+-        y += inc;
+-    }
+-
+-    QTAILQ_FOREACH(vs, &vd->clients, next) {
+-        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+-            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
+-        }
+-    }
+-}
+-
+ static void vnc_mouse_set(DisplayChangeListener *dcl,
+                           int x, int y, int visible)
+ {
+@@ -873,13 +785,6 @@ static int find_and_clear_dirty_height(struct VncState *vs,
+     return h;
+ }
+ 
+-static int vnc_update_client_sync(VncState *vs, int has_dirty)
+-{
+-    int ret = vnc_update_client(vs, has_dirty);
+-    vnc_jobs_join(vs);
+-    return ret;
+-}
+-
+ static int vnc_update_client(VncState *vs, int has_dirty)
+ {
+     if (vs->need_update && vs->csock != -1) {
+@@ -2912,7 +2817,6 @@ static void vnc_listen_websocket_read(void *opaque)
+ static const DisplayChangeListenerOps dcl_ops = {
+     .dpy_name          = "vnc",
+     .dpy_refresh       = vnc_refresh,
+-    .dpy_gfx_copy      = vnc_dpy_copy,
+     .dpy_gfx_update    = vnc_dpy_update,
+     .dpy_gfx_switch    = vnc_dpy_switch,
+     .dpy_mouse_set     = vnc_mouse_set,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch b/SOURCES/kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch
new file mode 100644
index 0000000..a8641a6
--- /dev/null
+++ b/SOURCES/kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch
@@ -0,0 +1,64 @@
+From d27fae125c1efd59ba3263260d41f8e054b070a2 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 21 Mar 2017 09:58:01 +0100
+Subject: [PATCH 1/7] fix :cirrus_vga fix OOB read case qemu Segmentation fault
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1490090287-1503-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 74419
+O-Subject: [RHEL-7.4 qemu-kvm PATCH 1/7] fix :cirrus_vga fix OOB read case qemu Segmentation fault
+Bugzilla: 1430059
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+From: hangaohuai <hangaohuai@huawei.com>
+
+check the validity of parameters in cirrus_bitblt_rop_fwd_transp_xxx
+and cirrus_bitblt_rop_fwd_xxx to avoid the OOB read which causes qemu Segmentation fault.
+
+After the fix, we will touch the assert in
+cirrus_invalidate_region:
+assert(off_cur_end >= off_cur);
+
+Signed-off-by: fangying <fangying1@huawei.com>
+Signed-off-by: hangaohuai <hangaohuai@huawei.com>
+Message-id: 20170314063919.16200-1-hangaohuai@huawei.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+(cherry picked from commit 215902d7b6fb50c6fc216fc74f770858278ed904)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/cirrus_vga_rop.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
+index 9c7bb09..a4f96c6 100644
+--- a/hw/display/cirrus_vga_rop.h
++++ b/hw/display/cirrus_vga_rop.h
+@@ -98,6 +98,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
+     uint8_t p;
+     dstpitch -= bltwidth;
+     srcpitch -= bltwidth;
++
++    if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
++        return;
++    }
++
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+ 	    p = *dst;
+@@ -144,6 +149,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
+     uint8_t p1, p2;
+     dstpitch -= bltwidth;
+     srcpitch -= bltwidth;
++
++    if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
++        return;
++    }
++
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x+=2) {
+ 	    p1 = *dst;
+-- 
+1.8.3.1
+
diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec
index 66a2a5f..2f9a30f 100644
--- a/SPECS/qemu-kvm.spec
+++ b/SPECS/qemu-kvm.spec
@@ -76,7 +76,7 @@ Obsoletes: %1 < %{obsoletes_version}                                      \
 Summary: QEMU is a FAST! processor emulator
 Name: %{pkgname}%{?pkgsuffix}
 Version: 1.5.3
-Release: 126%{?dist}.5
+Release: 126%{?dist}.6
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 Epoch: 10
 License: GPLv2+ and LGPLv2+ and BSD
@@ -3432,6 +3432,20 @@ Patch1686: kvm-cirrus-fix-patterncopy-checks.patch
 Patch1687: kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch
 # For bz#1420490 - EMBARGOED CVE-2017-2620 qemu-kvm: Qemu: display: cirrus: potential arbitrary code execution via cirrus_bitblt_cputovideo [rhel-7.3.z]
 Patch1688: kvm-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1689: kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1690: kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1691: kvm-cirrus-add-option-to-disable-blitter.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1692: kvm-cirrus-fix-cirrus_invalidate_region.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1693: kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1694: kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
+# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
+Patch1695: kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
 
 
 BuildRequires: zlib-devel
@@ -5300,6 +5314,13 @@ cp %{SOURCE18} pc-bios # keep "make check" happy
 %patch1686 -p1
 %patch1687 -p1
 %patch1688 -p1
+%patch1689 -p1
+%patch1690 -p1
+%patch1691 -p1
+%patch1692 -p1
+%patch1693 -p1
+%patch1694 -p1
+%patch1695 -p1
 
 %build
 buildarch="%{kvm_target}-softmmu"
@@ -5745,6 +5766,17 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || :
 %{_mandir}/man8/qemu-nbd.8*
 
 %changelog
+* Fri Mar 24 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.6
+- kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch [bz#1430059]
+- kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch [bz#1430059]
+- kvm-cirrus-add-option-to-disable-blitter.patch [bz#1430059]
+- kvm-cirrus-fix-cirrus_invalidate_region.patch [bz#1430059]
+- kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch [bz#1430059]
+- kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch [bz#1430059]
+- kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch [bz#1430059]
+- Resolves: bz#1430059
+  (CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z])
+
 * Mon Feb 13 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.5
 - kvm-cirrus-fix-patterncopy-checks.patch [bz#1420490]
 - kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch [bz#1420490]