a05f9de
From 14870ff4617fd482054ceb2f307a91582e5e8817 Mon Sep 17 00:00:00 2001
a05f9de
From: Peter Jones <pjones@redhat.com>
a05f9de
Date: Thu, 18 Apr 2013 13:10:53 -0400
a05f9de
Subject: [PATCH] Use memcpy instead of direct assignment for complex values.
a05f9de
 (#949761)
a05f9de
a05f9de
gcc 4.8.0 will emit SSE copies for such large chunks of data, and that
a05f9de
means using XMM0, which the UEFI ABI forbids.
a05f9de
a05f9de
So with 4.7.2, you get:
a05f9de
000000000000000f <canvas_set_bounds>:
a05f9de
   f:   48 8b 06                mov    (%rsi),%rax
a05f9de
  12:   48 89 47 38             mov    %rax,0x38(%rdi)
a05f9de
  16:   48 8b 46 08             mov    0x8(%rsi),%rax
a05f9de
  1a:   48 89 47 40             mov    %rax,0x40(%rdi)
a05f9de
  1e:   c3                      retq
a05f9de
a05f9de
And with 4.8.0 you get:
a05f9de
000000000000000f <canvas_set_bounds>:
a05f9de
   f:   48 83 ec 18             sub    $0x18,%rsp
a05f9de
  13:   0f 10 06                movups (%rsi),%xmm0
a05f9de
  16:   0f 29 04 24             movaps %xmm0,(%rsp)
a05f9de
  1a:   0f 11 47 38             movups %xmm0,0x38(%rdi)
a05f9de
  1e:   48 83 c4 18             add    $0x18,%rsp
a05f9de
  22:   c3                      retq
a05f9de
a05f9de
As soon as we hit the movaps, we hit a trap. Once we do, though, since the
a05f9de
memory pointed at by the IDT is basically random memory during UEFI execution,
a05f9de
we find our CPU looping between the entry point for #UD (invalid opcode) and
a05f9de
the first piece of garbage in RAM after it.
a05f9de
a05f9de
Right now, we have two options.  Either 1) trick the compiler into not
a05f9de
emitting that sequence of instructions, or 2) turn off SSE instruction
a05f9de
generation.  Number 2 currently requires making gnulib's printf not use
a05f9de
double or long double.  It's probably the right thing to do, but I'm not
a05f9de
sure what the right way to do it is.
a05f9de
a05f9de
So the following is method #1.
a05f9de
---
a05f9de
 grub-core/gfxmenu/gui_box.c               | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_canvas.c            | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_circular_progress.c | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_image.c             | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_label.c             | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_list.c              | 4 ++--
a05f9de
 grub-core/gfxmenu/gui_progress_bar.c      | 4 ++--
a05f9de
 7 files changed, 14 insertions(+), 14 deletions(-)
a05f9de
a05f9de
diff --git a/grub-core/gfxmenu/gui_box.c b/grub-core/gfxmenu/gui_box.c
a05f9de
index 38b15f9..702f844 100644
a05f9de
--- a/grub-core/gfxmenu/gui_box.c
a05f9de
+++ b/grub-core/gfxmenu/gui_box.c
a05f9de
@@ -264,7 +264,7 @@ static void
a05f9de
 box_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_box_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
   self->layout_func (self, 1, 0, 0);   /* Relayout the children.  */
a05f9de
 }
a05f9de
 
a05f9de
@@ -272,7 +272,7 @@ static void
a05f9de
 box_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_box_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 /* The box's preferred size is based on the preferred sizes
a05f9de
diff --git a/grub-core/gfxmenu/gui_canvas.c b/grub-core/gfxmenu/gui_canvas.c
a05f9de
index b3919c2..3d4fae9 100644
a05f9de
--- a/grub-core/gfxmenu/gui_canvas.c
a05f9de
+++ b/grub-core/gfxmenu/gui_canvas.c
a05f9de
@@ -160,14 +160,14 @@ static void
a05f9de
 canvas_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_canvas_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
 canvas_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_canvas_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static grub_err_t
a05f9de
diff --git a/grub-core/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c
a05f9de
index e06d40c..f7684cc 100644
a05f9de
--- a/grub-core/gfxmenu/gui_circular_progress.c
a05f9de
+++ b/grub-core/gfxmenu/gui_circular_progress.c
a05f9de
@@ -202,14 +202,14 @@ static void
a05f9de
 circprog_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   circular_progress_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
 circprog_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   circular_progress_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c
a05f9de
index 29784ed..d864096 100644
a05f9de
--- a/grub-core/gfxmenu/gui_image.c
a05f9de
+++ b/grub-core/gfxmenu/gui_image.c
a05f9de
@@ -158,7 +158,7 @@ static void
a05f9de
 image_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_image_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
   rescale_image (self);
a05f9de
 }
a05f9de
 
a05f9de
@@ -166,7 +166,7 @@ static void
a05f9de
 image_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_image_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 /* FIXME: inform rendering system it's not forced minimum.  */
a05f9de
diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c
a05f9de
index 637578f..daf6290 100644
a05f9de
--- a/grub-core/gfxmenu/gui_label.c
a05f9de
+++ b/grub-core/gfxmenu/gui_label.c
a05f9de
@@ -134,14 +134,14 @@ static void
a05f9de
 label_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_label_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
 label_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_label_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c
a05f9de
index 1982d9a..23b29ba 100644
a05f9de
--- a/grub-core/gfxmenu/gui_list.c
a05f9de
+++ b/grub-core/gfxmenu/gui_list.c
a05f9de
@@ -362,14 +362,14 @@ static void
a05f9de
 list_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   list_impl_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
 list_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   list_impl_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c
a05f9de
index 965c6b3..4e458e9 100644
a05f9de
--- a/grub-core/gfxmenu/gui_progress_bar.c
a05f9de
+++ b/grub-core/gfxmenu/gui_progress_bar.c
a05f9de
@@ -232,14 +232,14 @@ static void
a05f9de
 progress_bar_set_bounds (void *vself, const grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_progress_bar_t self = vself;
a05f9de
-  self->bounds = *bounds;
a05f9de
+  memcpy(&self->bounds, bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
 progress_bar_get_bounds (void *vself, grub_video_rect_t *bounds)
a05f9de
 {
a05f9de
   grub_gui_progress_bar_t self = vself;
a05f9de
-  *bounds = self->bounds;
a05f9de
+  memcpy(bounds, &self->bounds, sizeof (*bounds));
a05f9de
 }
a05f9de
 
a05f9de
 static void
a05f9de
-- 
a05f9de
1.8.2.1
a05f9de