a05f9de1dc
Signed-off-by: Peter Jones <pjones@redhat.com>
201 lines
6.5 KiB
Diff
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
|
|
|