From 14870ff4617fd482054ceb2f307a91582e5e8817 Mon Sep 17 00:00:00 2001 From: Peter Jones 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 : 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 : 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