|
|
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 |
|