grub2/0364-Use-memcpy-instead-of-direct-assignment-for-complex-.patch
Peter Jones a05f9de1dc Include bz number
Signed-off-by: Peter Jones <pjones@redhat.com>
2013-05-02 16:54:13 -04:00

201 lines
6.5 KiB
Diff

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