From 73f6ce4ab24fe5b7e1965402e62b8811014a4588 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 12 Jan 2010 23:30:52 +0100 Subject: [PATCH] x86_64 support for relocator --- conf/i386.rmk | 2 +- conf/x86_64-efi.rmk | 4 +++- lib/i386/relocator.c | 28 +++++++++++++++++++++------- lib/i386/relocator16.S | 4 ++-- lib/i386/relocator32.S | 2 +- lib/i386/relocator64.S | 4 ++-- lib/relocator.c | 16 ++++++++-------- 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/conf/i386.rmk b/conf/i386.rmk index 2efd9895a..d7417f444 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -18,7 +18,7 @@ vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += relocator.mod relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \ lib/i386/relocator64.S lib/i386/relocator16.S \ - lib/i386/relocator_asm.S lib/i386/relocator.c + lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c relocator_mod_CFLAGS = $(COMMON_CFLAGS) relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 19220610d..36d6579de 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -167,7 +167,9 @@ xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) xnu_mod_ASFLAGS = $(COMMON_ASFLAGS) pkglib_MODULES += relocator.mod -relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S +relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \ + lib/i386/relocator64.S lib/i386/relocator16.S \ + lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c relocator_mod_CFLAGS = $(COMMON_CFLAGS) relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/lib/i386/relocator.c b/lib/i386/relocator.c index 5757bb6df..d040c80ab 100644 --- a/lib/i386/relocator.c +++ b/lib/i386/relocator.c @@ -77,7 +77,11 @@ extern grub_addr_t grub_relocator64_cr3; grub_size_t grub_relocator_align = 1; grub_size_t grub_relocator_forward_size; grub_size_t grub_relocator_backward_size; -grub_size_t grub_relocator_jumper_size = 10; +#ifdef __x86_64__ +grub_size_t grub_relocator_jumper_size = 12; +#else +grub_size_t grub_relocator_jumper_size = 7; +#endif void grub_cpu_relocator_init (void) @@ -91,16 +95,26 @@ grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) { grub_uint8_t *ptr; ptr = rels; - /* movl $addr, %eax (for relocator) */ +#ifdef __x86_64__ + /* movq imm64, %rax (for relocator) */ + *(grub_uint8_t *) ptr = 0x48; + ptr++; + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint64_t *) ptr = addr; + ptr += sizeof (grub_uint64_t); +#else + /* movl imm32, %eax (for relocator) */ *(grub_uint8_t *) ptr = 0xb8; ptr++; *(grub_uint32_t *) ptr = addr; - ptr += 4; - /* jmp $addr */ - *(grub_uint8_t *) ptr = 0xe9; + ptr += sizeof (grub_uint32_t); +#endif + /* jmp $eax/$rax */ + *(grub_uint8_t *) ptr = 0xff; + ptr++; + *(grub_uint8_t *) ptr = 0xe0; ptr++; - *(grub_uint32_t *) ptr = addr - (grub_uint32_t) (ptr + 4); - ptr += 4; } void diff --git a/lib/i386/relocator16.S b/lib/i386/relocator16.S index d35adecd8..7d65e4dbe 100644 --- a/lib/i386/relocator16.S +++ b/lib/i386/relocator16.S @@ -21,7 +21,7 @@ #ifdef __x86_64__ #define RAX %rax -#define RSI %rdi +#define RSI %rsi #else #define RAX %eax #define RSI %esi @@ -93,7 +93,7 @@ LOCAL(cont1): movl %esi, %eax shrl $4, %eax - movw %ax, (LOCAL (segment) - LOCAL (base)) (RSI, 1) + movw %ax, (LOCAL (segment) - LOCAL (base)) (%esi, 1) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) diff --git a/lib/i386/relocator32.S b/lib/i386/relocator32.S index 4e0553c03..4f79151e2 100644 --- a/lib/i386/relocator32.S +++ b/lib/i386/relocator32.S @@ -21,7 +21,7 @@ #ifdef __x86_64__ #define RAX %rax -#define RSI %rdi +#define RSI %rsi #else #define RAX %eax #define RSI %esi diff --git a/lib/i386/relocator64.S b/lib/i386/relocator64.S index 42f61e32e..05627fb90 100644 --- a/lib/i386/relocator64.S +++ b/lib/i386/relocator64.S @@ -21,7 +21,7 @@ #ifdef __x86_64__ #define RAX %rax -#define RSI %rdi +#define RSI %rsi #else #define RAX %eax #define RSI %esi @@ -82,7 +82,7 @@ VARIABLE(grub_relocator64_cr3) .byte 0xb8 VARIABLE(grub_relocator64_cr3) .quad 0 - movl %rax, %cr3 + movq %rax, %cr3 #endif /* Load GDT. */ lgdt (LOCAL(gdtdesc) - LOCAL(base)) (RSI, 1) diff --git a/lib/relocator.c b/lib/relocator.c index a5b3c6daf..84ead99b1 100644 --- a/lib/relocator.c +++ b/lib/relocator.c @@ -40,7 +40,7 @@ grub_relocator_new (void) ret->postchunks = ~(grub_addr_t) 0; ret->relocators_size = grub_relocator_jumper_size; - grub_dprintf ("relocator", "relocators_size=%d\n", ret->relocators_size); + grub_dprintf ("relocator", "relocators_size=%ld\n", ret->relocators_size); return ret; } @@ -103,7 +103,7 @@ get_best_header (struct grub_relocator *rel, hb = h; hbp = hp; *best_addr = addr; - grub_dprintf ("relocator", "picked %p/%x\n", hb, addr); + grub_dprintf ("relocator", "picked %p/%lx\n", hb, addr); } } else @@ -146,7 +146,7 @@ get_best_header (struct grub_relocator *rel, hb = h; hbp = hp; *best_addr = addr; - grub_dprintf ("relocator", "picked %p/%x\n", hb, addr); + grub_dprintf ("relocator", "picked %p/%lx\n", hb, addr); } } } @@ -221,7 +221,7 @@ malloc_in_range (struct grub_relocator *rel, hb = get_best_header (rel, start, end, align, size, rb, &hbp, &best_addr, from_low_priv, collisioncheck); - grub_dprintf ("relocator", "best header %p/%x\n", hb, best_addr); + grub_dprintf ("relocator", "best header %p/%lx\n", hb, best_addr); if (!hb) { @@ -421,14 +421,14 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src, rel->highestnonpostaddr = start + size; } - grub_dprintf ("relocator", "relocators_size=%d\n", rel->relocators_size); + grub_dprintf ("relocator", "relocators_size=%ld\n", rel->relocators_size); if (start < target) rel->relocators_size += grub_relocator_backward_size; if (start > target) rel->relocators_size += grub_relocator_forward_size; - grub_dprintf ("relocator", "relocators_size=%d\n", rel->relocators_size); + grub_dprintf ("relocator", "relocators_size=%ld\n", rel->relocators_size); chunk->src = start; chunk->target = target; @@ -485,7 +485,7 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, } adjust_limits (rel, &min_addr2, &max_addr2, min_addr, max_addr); - grub_dprintf ("relocator", "Adjusted limits from %x-%x to %x-%x\n", + grub_dprintf ("relocator", "Adjusted limits from %lx-%lx to %lx-%lx\n", min_addr, max_addr, min_addr2, max_addr2); do @@ -572,7 +572,7 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, grub_addr_t rels; grub_addr_t rels0; - grub_dprintf ("relocator", "Preparing relocs (size=%d)\n", + grub_dprintf ("relocator", "Preparing relocs (size=%ld)\n", rel->relocators_size); if (!malloc_in_range (rel, 0, ~(grub_addr_t)0 - rel->relocators_size + 1,