Split early startup code out of armv7_start.S into locore0.S. Adjust
authorpatrick <patrick@openbsd.org>
Wed, 14 Jun 2017 13:12:49 +0000 (13:12 +0000)
committerpatrick <patrick@openbsd.org>
Wed, 14 Jun 2017 13:12:49 +0000 (13:12 +0000)
link run so that this locore0.o is always at the start of the
executable.  But randomize the link order of all other .o files in the
kernel, so that their exec/rodata/data/bss segments land all over the
place.  Note that this commit does not yet unmap the early bootcode
since this is not as easy as on arm64.

As a result, the internal layout of every newly build bsd kernel is
different from past kernels.  Internal relative offsets are not known
to an outside attacker.  The only known offsets are in the startup code,
which has been unmapped.

Ramdisk kernels cannot be compiled like this, because they are gzip'd.
When the internal pointer references change, the compression dictionary
bloats and results in poorer compression.

With guidance and ok deraadt@

sys/arch/armv7/armv7/armv7_start.S
sys/arch/armv7/armv7/locore0.S [new file with mode: 0644]
sys/arch/armv7/conf/Makefile.armv7
sys/arch/armv7/conf/files.armv7

index 4d49b34..aa027b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: armv7_start.S,v 1.13 2017/01/07 15:44:28 kettenis Exp $       */
+/*     $OpenBSD: armv7_start.S,v 1.14 2017/06/14 13:12:49 patrick Exp $        */
 /*     $NetBSD: lubbock_start.S,v 1.1 2003/06/18 10:51:15 bsh Exp $ */
 
 /*
 #undef DOMAIN_CLIENT   /* XXX */
 #include "assym.h"
 
-#define ELR    .long   0xe12ef30e              @ msr   ELR_hyp, lr
-#define ERET   .long   0xe160006e              @ eret
 #define HVC    .word   0xe1400070              @ hvc
 
-/*
- * CPWAIT -- Canonical method to wait for CP15 update.
- * NOTE: Clobbers the specified temp reg.
- * copied from arm/arm/cpufunc_asm_xscale.S
- * XXX: better be in a common header file.
- */
-#define        CPWAIT_BRANCH                                                    \
-       sub     pc, pc, #4
-
-#define        CPWAIT(tmp)                                                      \
-       mrc     CP15_TTBR0(tmp)         /* arbitrary read of CP15 */    ;\
-       mov     tmp, tmp                /* wait for it to complete */   ;\
-       CPWAIT_BRANCH                   /* branch to next insn */
-       
-/*
- * Kernel start routine for OMAP
- * this code is excuted at the very first after the kernel is loaded
- * by U-Boot.
- *
- * This code makes a number of assumptions.
- * 1) it is running in RAM.
- * 2) it is run at a fairly well known offset from the beginning of
- *    a ram section.
- * 3) the memory region around the kernel will be at least about 32MB
- * 4) memory just below the kernel can be used by the kernel
- * 5) memory at the start of the ram section may not be useable
- *    it may contain bootloader/u-boot
- * 6) the fdt/kernel parameters in arg r0-r2 may point outside the
- *    32MB of ram (it likely should be copied very early)
- *
- */
-       .text
-
-       .global _C_LABEL(bootstrap_start)
-_C_LABEL(bootstrap_start):
-       /* Save U-Boot arguments */
-       mov     r6, r0
-       mov     r7, r1
-       mov     r8, r2
-
-       /*
-        *  Kernel is loaded in SDRAM (0xX0200000..), and is expected to run
-        *  in VA 0xc0200000..
-        *
-        * which base memory address the kernel is located is unknown
-        * however the kernel should be located at 0x00300000 offset
-        * from that ram area. copy the PC into a register and strip
-        * the low bits
-        */
-
-       /*
-        * If we are running in HYP mode, try to get to SVC safely.
-        * Ensure IRQ, FIQ and Aborts are disabled in HYP mode before
-        * going to SVC.  If we are there already, just go ahead.
-        */
-       mrs     r0, cpsr
-       and     r0, r0, #(PSR_MODE)
-       teq     r0, #(PSR_HYP32_MODE)
-       bne     1f                      /* If we are not in HYP, we're done */
-       mrs     r0, cpsr
-       bic     r0, r0, #(PSR_MODE)
-       orr     r0, r0, #(PSR_SVC32_MODE)
-       orr     r0, r0, #(PSR_I | PSR_F | PSR_A)
-       msr     spsr_fsxc, r0
-       adr     lr, 1f
-       ELR
-       ERET                            /* Use the HYP LR to get into SVC */
-1:
-
-       /*
-        * Now that we are in SVC, build up pagetables and start up.
-        */
-       mov r9, pc
-       and r9, r9, #0xf0000000 // Leave the memory base in r9
-
-       /* create the bootstrap MMU table at offset 0x00200000 */
-       orr     r0, r9, #0x00200000
-       mov     r3, #0
-       mov     r2, #0
-2:
-       str     r3, [r0, r2]
-       add     r2, r2, #4
-       cmp     r2, #(L1_TABLE_SIZE)
-       bne     2b
-
-       adr     r4, mmu_init_table
-
-       mov     r2, r9, lsr #18
-       ldr     r3, [r4, #8]
-       bic     r3, r3, #0xf0000000
-       orr     r3, r3, r9
-       str     r2, [r4, #4]
-       str     r3, [r4, #8]
-       str     r3, [r4, #0x14] // ram address for 0xc0000000
-
-       /*
-        * the first entry has two fields that need to be updated for
-        * specific ram configuration of this board.
-        */
-       b       4f
-
-3:
-       str     r3, [r0, r2]
-       add     r2, r2, #4
-       add     r3, r3, #(L1_S_SIZE)
-       adds    r1, r1, #-1
-       bhi     3b
-4:     
-       ldmia   r4!, {r1,r2,r3}   /* # of sections, PA|attr, VA */
-       cmp     r1, #0
-       bne     3b      
-
-       mcr     CP15_TTBR0(r0)          /* Set TTB */
-       mcr     CP15_TLBIALL(r0)        /* Flush TLB */
-
-       /* Set the Domain Access register.  Very important! */
-       mov     r0, #DOMAIN_CLIENT      /* We only use domain 0 */
-       mcr     CP15_DACR(r0)   
-
-       /* Enable MMU */
-       mrc     CP15_SCTLR(r0)  
-       orr     r0, r0, #CPU_CONTROL_MMU_ENABLE
-       mcr     CP15_SCTLR(r0)  
-       CPWAIT(r0)
-
-       /* Restore U-Boot arguments */
-       mov     r0, r6
-       mov     r1, r7
-       mov     r2, r8
-       mov     r3, r9
-
-       /* Jump to kernel code in TRUE VA */
-       adr     r6, Lstart
-       ldr     pc, [r6]
-
-Lstart:
-       .word   start
-
-#define MMU_INIT(va,pa,n_sec,attr) \
-       .word   n_sec                                       ; \
-       .word   4*((va)>>L1_S_SHIFT)                        ; \
-       .word   (pa)|(attr)                                 ;
-
-mmu_init_table:
-       /* map SDRAM VA==PA, WT cacheable */
-       MMU_INIT(0x00000000, 0x00000000, 64,
-                L1_TYPE_S|L1_S_C|L1_S_V7_AP(AP_KRW)|L1_S_V7_AF)
-       /* map VA 0xc0000000..0xc3ffffff to PA */
-       MMU_INIT(0xc0000000, 0x00000000, 64,
-                L1_TYPE_S|L1_S_C|L1_S_V7_AP(AP_KRW)|L1_S_V7_AF)
-
-       .word 0 /* end of table */
-
        .text
 
 ENTRY(smc_call)
diff --git a/sys/arch/armv7/armv7/locore0.S b/sys/arch/armv7/armv7/locore0.S
new file mode 100644 (file)
index 0000000..2a4e98c
--- /dev/null
@@ -0,0 +1,197 @@
+/*     $OpenBSD: locore0.S,v 1.1 2017/06/14 13:12:49 patrick Exp $     */
+/*     $NetBSD: lubbock_start.S,v 1.1 2003/06/18 10:51:15 bsh Exp $ */
+
+/*
+ * Copyright (c) 2002, 2003  Genetec Corporation.  All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of Genetec Corporation may not be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <arm/sysreg.h>
+#include <arm/armreg.h>
+#include <arm/pte.h>
+
+#undef DOMAIN_CLIENT   /* XXX */
+#include "assym.h"
+
+#define ELR    .long   0xe12ef30e              @ msr   ELR_hyp, lr
+#define ERET   .long   0xe160006e              @ eret
+
+/*
+ * CPWAIT -- Canonical method to wait for CP15 update.
+ * NOTE: Clobbers the specified temp reg.
+ * copied from arm/arm/cpufunc_asm_xscale.S
+ * XXX: better be in a common header file.
+ */
+#define        CPWAIT_BRANCH                                                    \
+       sub     pc, pc, #4
+
+#define        CPWAIT(tmp)                                                      \
+       mrc     CP15_TTBR0(tmp)         /* arbitrary read of CP15 */    ;\
+       mov     tmp, tmp                /* wait for it to complete */   ;\
+       CPWAIT_BRANCH                   /* branch to next insn */
+
+/*
+ * Kernel start routine for OMAP
+ * this code is excuted at the very first after the kernel is loaded
+ * by U-Boot.
+ *
+ * This code makes a number of assumptions.
+ * 1) it is running in RAM.
+ * 2) it is run at a fairly well known offset from the beginning of
+ *    a ram section.
+ * 3) the memory region around the kernel will be at least about 32MB
+ * 4) memory just below the kernel can be used by the kernel
+ * 5) memory at the start of the ram section may not be useable
+ *    it may contain bootloader/u-boot
+ * 6) the fdt/kernel parameters in arg r0-r2 may point outside the
+ *    32MB of ram (it likely should be copied very early)
+ *
+ */
+       .text
+
+       .global _C_LABEL(bootstrap_start)
+_C_LABEL(bootstrap_start):
+       /* Save U-Boot arguments */
+       mov     r6, r0
+       mov     r7, r1
+       mov     r8, r2
+
+       /*
+        *  Kernel is loaded in SDRAM (0xX0200000..), and is expected to run
+        *  in VA 0xc0200000..
+        *
+        * which base memory address the kernel is located is unknown
+        * however the kernel should be located at 0x00300000 offset
+        * from that ram area. copy the PC into a register and strip
+        * the low bits
+        */
+
+       /*
+        * If we are running in HYP mode, try to get to SVC safely.
+        * Ensure IRQ, FIQ and Aborts are disabled in HYP mode before
+        * going to SVC.  If we are there already, just go ahead.
+        */
+       mrs     r0, cpsr
+       and     r0, r0, #(PSR_MODE)
+       teq     r0, #(PSR_HYP32_MODE)
+       bne     1f                      /* If we are not in HYP, we're done */
+       mrs     r0, cpsr
+       bic     r0, r0, #(PSR_MODE)
+       orr     r0, r0, #(PSR_SVC32_MODE)
+       orr     r0, r0, #(PSR_I | PSR_F | PSR_A)
+       msr     spsr_fsxc, r0
+       adr     lr, 1f
+       ELR
+       ERET                            /* Use the HYP LR to get into SVC */
+1:
+
+       /*
+        * Now that we are in SVC, build up pagetables and start up.
+        */
+       mov r9, pc
+       and r9, r9, #0xf0000000 // Leave the memory base in r9
+
+       /* create the bootstrap MMU table at offset 0x00200000 */
+       orr     r0, r9, #0x00200000
+       mov     r3, #0
+       mov     r2, #0
+2:
+       str     r3, [r0, r2]
+       add     r2, r2, #4
+       cmp     r2, #(L1_TABLE_SIZE)
+       bne     2b
+
+       adr     r4, mmu_init_table
+
+       mov     r2, r9, lsr #18
+       ldr     r3, [r4, #8]
+       bic     r3, r3, #0xf0000000
+       orr     r3, r3, r9
+       str     r2, [r4, #4]
+       str     r3, [r4, #8]
+       str     r3, [r4, #0x14] // ram address for 0xc0000000
+
+       /*
+        * the first entry has two fields that need to be updated for
+        * specific ram configuration of this board.
+        */
+       b       4f
+
+3:
+       str     r3, [r0, r2]
+       add     r2, r2, #4
+       add     r3, r3, #(L1_S_SIZE)
+       adds    r1, r1, #-1
+       bhi     3b
+4:
+       ldmia   r4!, {r1,r2,r3}   /* # of sections, PA|attr, VA */
+       cmp     r1, #0
+       bne     3b
+
+       mcr     CP15_TTBR0(r0)          /* Set TTB */
+       mcr     CP15_TLBIALL(r0)        /* Flush TLB */
+
+       /* Set the Domain Access register.  Very important! */
+       mov     r0, #DOMAIN_CLIENT      /* We only use domain 0 */
+       mcr     CP15_DACR(r0)
+
+       /* Enable MMU */
+       mrc     CP15_SCTLR(r0)
+       orr     r0, r0, #CPU_CONTROL_MMU_ENABLE
+       mcr     CP15_SCTLR(r0)
+       CPWAIT(r0)
+
+       /* Restore U-Boot arguments */
+       mov     r0, r6
+       mov     r1, r7
+       mov     r2, r8
+       mov     r3, r9
+
+       /* Jump to kernel code in TRUE VA */
+       adr     r6, Lstart
+       ldr     pc, [r6]
+
+Lstart:
+       .word   start
+
+#define MMU_INIT(va,pa,n_sec,attr) \
+       .word   n_sec                                       ; \
+       .word   4*((va)>>L1_S_SHIFT)                        ; \
+       .word   (pa)|(attr)                                 ;
+
+mmu_init_table:
+       /* map SDRAM VA==PA, WT cacheable */
+       MMU_INIT(0x00000000, 0x00000000, 64,
+                L1_TYPE_S|L1_S_C|L1_S_V7_AP(AP_KRW)|L1_S_V7_AF)
+       /* map VA 0xc0000000..0xc3ffffff to PA */
+       MMU_INIT(0xc0000000, 0x00000000, 64,
+                L1_TYPE_S|L1_S_C|L1_S_V7_AP(AP_KRW)|L1_S_V7_AF)
+
+       .word 0 /* end of table */
+
+       .text
index bd893b4..b9fb44d 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile.armv7,v 1.26 2017/06/13 16:40:01 deraadt Exp $
+#      $OpenBSD: Makefile.armv7,v 1.27 2017/06/14 13:12:49 patrick Exp $
 
 # For instructions on building kernels consult the config(8) and options(4)
 # manual pages.
@@ -29,9 +29,13 @@ CWARNFLAGS=  -Werror -Wall -Wimplicit-function-declaration \
 
 CMACHFLAGS=    -msoft-float -march=armv6 -Wa,-march=armv7a
 CMACHFLAGS+=   -ffreestanding ${NOPIE_FLAGS}
+SORTR=         sort -R
 .if ${IDENT:M-DNO_PROPOLICE}
 CMACHFLAGS+=   -fno-stack-protector
 .endif
+.if ${IDENT:M-DSMALL_KERNEL}
+SORTR=         cat
+.endif
 
 DEBUG?=                -g
 COPTS?=                -O2
@@ -65,13 +69,14 @@ NORMAL_S=   ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
 #      ${SYSTEM_LD_HEAD}
 #      ${SYSTEM_LD} swapxxx.o
 #      ${SYSTEM_LD_TAIL}
-SYSTEM_HEAD=   ${_mach}_start.o locore.o param.o ioconf.o
-SYSTEM_OBJ=    ${SYSTEM_HEAD} ${OBJS}
+SYSTEM_HEAD=   locore0.o gap.o
+SYSTEM_OBJ=    ${SYSTEM_HEAD} ${OBJS} param.o ioconf.o
 SYSTEM_DEP=    Makefile ${SYSTEM_OBJ} ld.script
 SYSTEM_LD_HEAD=        @rm -f $@
 SYSTEM_LD=     @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_HEAD} vers.o $${OBJS}'; \
                umask 007; \
-               ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} vers.o ${OBJS}
+               echo ${OBJS} param.o ioconf.o vers.o | tr " " "\n" | ${SORTR} > lorder; \
+               ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} `cat lorder`
 SYSTEM_LD_TAIL=        @${SIZE} $@
 
 .if ${DEBUG} == "-g"
@@ -127,8 +132,15 @@ vers.o: ${SYSTEM_DEP:Ngap.o} ${SYSTEM_SWAP_DEP}
        sh $S/conf/newvers.sh
        ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
 
+gap.S: ${SYSTEM_SWAP_DEP} Makefile
+       umask 007; sh $S/conf/makegap.sh 0xd4 > gap.S
+
+gap.o: gap.S
+       umask 007; ${CC} ${AFLAGS} ${CPPFLAGS} ${PROF} -c gap.S
+
 clean:
-       rm -f *bsd *bsd.gdb *.[dio] [a-z]*.s assym.* ${DB_STRUCTINFO} param.c
+       rm -f *bsd *bsd.gdb *.[dio] [a-z]*.s assym.* ${DB_STRUCTINFO} \
+           gap.S lorder param.c
 
 cleandir: clean
        rm -f Makefile *.h ioconf.c options machine ${_mach} vers.c
@@ -140,11 +152,10 @@ db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl
        objdump -g db_structinfo.o | perl $S/ddb/parse_structinfo.pl > $@
        rm -f db_structinfo.o
 
-${_mach}_start.o: ${_machdir}/${_mach}/${_mach}_start.S
-locore.o: ${_archdir}/${_arch}/locore.S assym.h
+locore0.o: ${_machdir}/${_mach}/locore0.S assym.h
 in_cksum_arm.o fiq_subr.o bcopyinout.o copystr.o sigcode.o: assym.h
 vectors.o cpuswitch7.o exception.o bcopy_page.o irq_dispatch.o: assym.h
-armv7_start.o: assym.h
+${_mach}_start.o locore.o: assym.h
 
 # The install target can be redefined by putting a
 # install-kernel-${MACHINE_NAME} target into /etc/mk.conf
index dab277f..cc2cf35 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.armv7,v 1.32 2017/03/09 20:13:12 kettenis Exp $
+#      $OpenBSD: files.armv7,v 1.33 2017/06/14 13:12:49 patrick Exp $
 
 maxpartitions  16
 maxusers       2 8 64
@@ -9,6 +9,7 @@ major   {cd = 26}
 major  {rd = 18}
 
 file   arch/arm/arm/conf.c
+file   arch/arm/arm/locore.S
 
 #interrupt API layer
 file   arch/armv7/armv7/intr.c
@@ -20,6 +21,7 @@ file  arch/arm/arm/softintr.c
 # Generic MD files
 file   arch/armv7/armv7/armv7.c
 file   arch/armv7/armv7/armv7_machdep.c
+file   arch/armv7/armv7/armv7_start.S
 file   arch/armv7/armv7/autoconf.c
 file   arch/armv7/armv7/platform.c
 file   arch/arm/arm/disksubr.c                 disk