diff --git a/acinclude.m4 b/acinclude.m4 index 49a1a75d1..faf90fb18 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -458,3 +458,23 @@ dnl program. AC_DEFUN([grub_TRANSFORM],[dnl AC_SUBST(AS_TR_SH([$1]), [`AS_ECHO([$1]) | sed "$program_transform_name"`])dnl ]) + +dnl Check if the C compiler supports `-mno-unaligned-access'. +AC_DEFUN([grub_CHECK_NO_UNALIGNED_ACCESS],[ +[# foobar +nua_possible=yes] +AC_MSG_CHECKING([whether `$CC' supports `-mno-unaligned-access']) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +int main() { + return 0; +} +]])]) + +[if eval "$ac_compile -S -mno-unaligned-access -o conftest.s" 2> /dev/null; then] + AC_MSG_RESULT([yes]) + [rm -f conftest.s +else + nua_possible=no] + AC_MSG_RESULT([no]) +[fi] +]) diff --git a/conf/Makefile.common b/conf/Makefile.common index d9b34714a..08fd2b0d6 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -38,10 +38,7 @@ if COND_sparc64_ieee1275 LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax endif if COND_arm -# Image entry point always in ARM (A32) state - ensure proper functionality if -# the rest is built for the Thumb (T32) state. - CFLAGS_PLATFORM += -mthumb-interwork -mno-unaligned-access -mlong-calls - CCASFLAGS_PLATFORM = -Wa,-mimplicit-it=thumb + CFLAGS_PLATFORM += -mthumb-interwork -mlong-calls LDFLAGS_PLATFORM = -Wl,--wrap=__clear_cache endif diff --git a/configure.ac b/configure.ac index ed8de8ab4..7ad6231d7 100644 --- a/configure.ac +++ b/configure.ac @@ -656,6 +656,14 @@ if test x"$sap_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" fi +# -mno-unaligned-access +if test "$target_cpu" = arm; then + grub_CHECK_NO_UNALIGNED_ACCESS + if test x"$nua_possible" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-unaligned-access" + fi +fi + AC_ARG_ENABLE([werror], [AS_HELP_STRING([--disable-werror], [do not use -Werror when building GRUB])]) diff --git a/grub-core/kern/arm/cache.S b/grub-core/kern/arm/cache.S index 6d7ed8537..dc1b63aea 100644 --- a/grub-core/kern/arm/cache.S +++ b/grub-core/kern/arm/cache.S @@ -17,19 +17,22 @@ */ #include -#include .file "cache.S" .text .syntax unified -#if !defined (__thumb2__) .arm -#define ARM(x...) x -#define THUMB(x...) +#if (__ARM_ARCH_6__ == 1) + .arch armv6 +# define DMB mcr p15, 0, r0, c7, c10, 5 +# define DSB mcr p15, 0, r0, c7, c10, 4 +# define ISB mcr p15, 0, r0, c7, c5, 4 +#elif (__ARM_ARCH_7A__ == 1) +# define DMB dmb +# define DSB dsb +# define ISB isb #else - .thumb -#define THUMB(x...) x -#define ARM(x...) +# error Unsupported architecture version! #endif .align 2 @@ -39,54 +42,43 @@ */ @ r0 - *beg (inclusive) -@ r1 - *end (exclusive) +@ r1 - *end (exclusive) clean_dcache_range: - @ Clean data cache range for range to point-of-unification + @ Clean data cache for range to point-of-unification ldr r2, dlinesz + sub r3, r2, #1 @ align "beg" to start of line + mvn r3, r3 + and r0, r0, r3 1: cmp r0, r1 bge 2f -#ifdef DEBUG - push {r0-r2, lr} - mov r1, r2 - mov r2, r0 - ldr r0, =dcstr - bl EXT_C(grub_printf) - pop {r0-r2, lr} -#endif mcr p15, 0, r0, c7, c11, 1 @ DCCMVAU add r0, r0, r2 @ Next line b 1b -2: dsb +2: DSB bx lr @ r0 - *beg (inclusive) -@ r1 - *end (exclusive) +@ r1 - *end (exclusive) invalidate_icache_range: @ Invalidate instruction cache for range to point-of-unification ldr r2, ilinesz + sub r3, r2, #1 @ align "beg" to start of line + mvn r3, r3 + and r0, r0, r3 1: cmp r0, r1 bge 2f -#ifdef DEBUG - push {r0-r2, lr} - mov r1, r2 - mov r2, r0 - ldr r0, =icstr - bl EXT_C(grub_printf) - pop {r0-r2, lr} -#endif mcr p15, 0, r0, c7, c5, 1 @ ICIMVAU add r0, r0, r2 @ Next line b 1b @ Branch predictor invalidate all 2: mcr p15, 0, r0, c7, c5, 6 @ BPIALL - dsb - isb + DSB + ISB bx lr - -@void __wrap___clear_cache(char *beg, char *end); -FUNCTION(__wrap___clear_cache) - dmb - dsb + +sync_caches: + DMB + DSB push {r4-r6, lr} ldr r2, probed @ If first call, probe cache sizes cmp r2, #0 @@ -103,7 +95,8 @@ probe_caches: push {r4-r6, lr} mrc p15, 0, r4, c0, c0, 1 @ Read Cache Type Register mov r5, #1 - ubfx r6, r4, #16, #4 @ Extract min D-cache num word log2 + lsr r6, r4, #16 @ Extract min D-cache num word log2 + and r6, r6, #0xf add r6, r6, #2 @ words->bytes lsl r6, r5, r6 @ Convert to num bytes ldr r3, =dlinesz @@ -117,11 +110,6 @@ probe_caches: str r5, [r3] pop {r4-r6, pc} -#ifdef DEBUG -dcstr: .asciz "cleaning %d bytes of D cache @ 0x%08x\n" -icstr: .asciz "invalidating %d bytes of I cache @ 0x%08x\n" -#endif - .align 3 probed: .long 0 dlinesz: @@ -132,7 +120,7 @@ ilinesz: @void grub_arch_sync_caches (void *address, grub_size_t len) FUNCTION(grub_arch_sync_caches) add r1, r0, r1 - b __wrap___clear_cache + b sync_caches @ r0 - CLIDR @ r1 - LoC @@ -149,21 +137,26 @@ FUNCTION(grub_arch_sync_caches) clean_invalidate_dcache: push {r4-r12, lr} mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR - ubfx r1, r0, #24, #3 @ Extract LoC - + lsr r1, r0, #24 @ Extract LoC + and r1, r1, #0x7 + mov r2, #0 @ First level, L1 2: and r8, r0, #7 @ cache type at current level cmp r8, #2 blt 5f @ instruction only, or none, skip level - @ set current cache level/type (for CSSIDR read) + @ set current cache level/type (for CCSIDR read) lsl r8, r2, #1 mcr p15, 2, r8, c0, c0, 0 @ Write CSSELR (level, type: data/uni) @ read current cache information - mrc p15, 1, r8, c0, c0, 0 @ Read CSSIDR - ubfx r3, r8, #13, #14 @ Number of sets -1 - ubfx r4, r8, #3, #9 @ Number of ways -1 + mrc p15, 1, r8, c0, c0, 0 @ Read CCSIDR + lsr r3, r8, #13 @ Number of sets -1 + ldr r9, =0x3fff + and r3, r3, r9 + lsr r4, r8, #3 @ Number of ways -1 + ldr r9, =0x1ff + and r4, r4, r9 and r7, r8, #7 @ log2(line size in words) - 2 add r7, r7, #2 @ adjust mov r8, #1 @@ -186,11 +179,11 @@ clean_invalidate_dcache: clz r9, r10 @ r9 = way field offset add r9, r9, #1 4: lsl r10, r6, r9 - orr r11, r8, r10 @ insert way field - - @ clean line by set/way + orr r11, r8, r10 @ insert way field + + @ clean and invalidate line by set/way mcr p15, 0, r11, c7, c14, 2 @ DCCISW - + @ next way add r6, r6, #1 cmp r6, r4 @@ -200,7 +193,7 @@ clean_invalidate_dcache: add r5, r5, #1 cmp r5, r3 ble 3b - + @ next level 5: lsr r0, r0, #3 @ align next level CLIDR 'type' field add r2, r2, #1 @ increment cache level counter @@ -208,8 +201,8 @@ clean_invalidate_dcache: blt 2b @ outer loop @ return -6: dsb - isb +6: DSB + ISB pop {r4-r12, pc} FUNCTION(grub_arm_disable_caches_mmu) @@ -219,8 +212,8 @@ FUNCTION(grub_arm_disable_caches_mmu) mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #(1 << 2) mcr p15, 0, r0, c1, c0, 0 - dsb - isb + DSB + ISB @ clean/invalidate D-cache bl clean_invalidate_dcache @@ -229,14 +222,14 @@ FUNCTION(grub_arm_disable_caches_mmu) mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #(1 << 12) mcr p15, 0, r0, c1, c0, 0 - dsb - isb + DSB + ISB @ invalidate I-cache (also invalidates branch predictors) mcr p15, 0, r0, c7, c5, 0 - dsb - isb - + DSB + ISB + @ clear SCTLR M bit mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #(1 << 0) @@ -244,8 +237,8 @@ FUNCTION(grub_arm_disable_caches_mmu) mcr p15, 0, r0, c8, c7, 0 @ invalidate TLB mcr p15, 0, r0, c7, c5, 6 @ invalidate branch predictor - dsb - isb + DSB + ISB pop {r4, pc} diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c index 1da37384a..ab4eec682 100644 --- a/grub-core/kern/uboot/init.c +++ b/grub-core/kern/uboot/init.c @@ -130,10 +130,9 @@ grub_machine_get_bootlocation (char **device, char **path) tmp = uboot_env_get ("grub_bootdev"); if (tmp) { - *device = grub_malloc (grub_strlen (tmp) + 1); + *device = grub_strdup (tmp); if (*device == NULL) return; - grub_strncpy (*device, tmp, grub_strlen (tmp) + 1); } else *device = NULL; @@ -141,10 +140,9 @@ grub_machine_get_bootlocation (char **device, char **path) tmp = uboot_env_get ("grub_bootpath"); if (tmp) { - *path = grub_malloc (grub_strlen (tmp) + 1); + *path = grub_strdup (tmp); if (*path == NULL) return; - grub_strncpy (*path, tmp, grub_strlen (tmp) + 1); } else *path = NULL; diff --git a/grub-core/lib/arm/setjmp.S b/grub-core/lib/arm/setjmp.S index 7038a229c..9054e073e 100644 --- a/grub-core/lib/arm/setjmp.S +++ b/grub-core/lib/arm/setjmp.S @@ -17,19 +17,10 @@ */ #include -#include .file "setjmp.S" .syntax unified -#if !defined (__thumb2__) .arm -#define ARM(x...) x -#define THUMB(x...) -#else - .thumb -#define THUMB(x...) x -#define ARM(x...) -#endif .text @@ -37,9 +28,7 @@ * int grub_setjmp (grub_jmp_buf env) */ FUNCTION(grub_setjmp) - THUMB( mov ip, sp ) - THUMB( stm r0, { r4-r11, ip, lr } ) - ARM( stm r0, { r4-r11, sp, lr } ) + stm r0, { r4-r11, sp, lr } mov r0, #0 bx lr @@ -47,9 +36,7 @@ FUNCTION(grub_setjmp) * int grub_longjmp (grub_jmp_buf env, int val) */ FUNCTION(grub_longjmp) - THUMB( ldm r0, { r4-r11, ip, lr } ) - THUMB( mov sp, ip ) - ARM( ldm r0, { r4-r11, sp, lr } ) + ldm r0, { r4-r11, sp, lr } movs r0, r1 moveq r0, #1 bx lr diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index 3038d5016..d101db473 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -121,6 +121,5 @@ void EXPORT_FUNC (__aeabi_llsl) (void); void EXPORT_FUNC (__aeabi_llsr) (void); void EXPORT_FUNC (__aeabi_uidiv) (void); void EXPORT_FUNC (__aeabi_uidivmod) (void); -void EXPORT_FUNC (__wrap___clear_cache) (void *, void *); void EXPORT_FUNC (__aeabi_ulcmp) (void); #endif diff --git a/include/grub/symbol.h b/include/grub/symbol.h index e2119bf35..390eb62f2 100644 --- a/include/grub/symbol.h +++ b/include/grub/symbol.h @@ -29,11 +29,7 @@ #if HAVE_ASM_USCORE #ifdef ASM_FILE -# ifndef (__arm__) -# define EXT_C(sym) _ ## sym -# else -# define EXT_C(sym) % ## sym -# endif +# define EXT_C(sym) _ ## sym #else # define EXT_C(sym) "_" sym #endif