From: patrick Date: Wed, 14 Jun 2017 13:12:49 +0000 (+0000) Subject: Split early startup code out of armv7_start.S into locore0.S. Adjust X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=bfb8ea58e3371e25437666d300d19af0bb1f5bbe;p=openbsd Split early startup code out of armv7_start.S into locore0.S. Adjust 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@ --- diff --git a/sys/arch/armv7/armv7/armv7_start.S b/sys/arch/armv7/armv7/armv7_start.S index 4d49b34bb65..aa027b3094f 100644 --- a/sys/arch/armv7/armv7/armv7_start.S +++ b/sys/arch/armv7/armv7/armv7_start.S @@ -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 $ */ /* @@ -38,163 +38,8 @@ #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 index 00000000000..2a4e98cbe8c --- /dev/null +++ b/sys/arch/armv7/armv7/locore0.S @@ -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 +#include +#include +#include + +#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 diff --git a/sys/arch/armv7/conf/Makefile.armv7 b/sys/arch/armv7/conf/Makefile.armv7 index bd893b46c5d..b9fb44d46c0 100644 --- a/sys/arch/armv7/conf/Makefile.armv7 +++ b/sys/arch/armv7/conf/Makefile.armv7 @@ -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 diff --git a/sys/arch/armv7/conf/files.armv7 b/sys/arch/armv7/conf/files.armv7 index dab277f2a5a..cc2cf356dce 100644 --- a/sys/arch/armv7/conf/files.armv7 +++ b/sys/arch/armv7/conf/files.armv7 @@ -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