summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2006-06-12 22:58:50 +0000
committercognet <cognet@FreeBSD.org>2006-06-12 22:58:50 +0000
commit5dcde5a0f3d635cf4b612a54a5446349e01ef3a5 (patch)
tree7e3daccc8b69c0e3ca895ce43f63acdaebb9b857 /sys
parente928591f2a68df33d466de1b5fdb769332dc30b0 (diff)
downloadFreeBSD-src-5dcde5a0f3d635cf4b612a54a5446349e01ef3a5.zip
FreeBSD-src-5dcde5a0f3d635cf4b612a54a5446349e01ef3a5.tar.gz
MFp4:
- Try hard to calculate a safe sp, so that the stack doesn't get smashed while uncompressing or relocating the kernel. - Bring in code needed to calculate the cacheline size etc, needed for arm9_idcache_wbinv_all.
Diffstat (limited to 'sys')
-rw-r--r--sys/arm/arm/elf_trampoline.c141
-rw-r--r--sys/arm/arm/inckern.S8
-rw-r--r--sys/conf/Makefile.arm4
3 files changed, 142 insertions, 11 deletions
diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c
index e250a47..83b749e 100644
--- a/sys/arm/arm/elf_trampoline.c
+++ b/sys/arm/arm/elf_trampoline.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/pte.h>
#include <machine/cpufunc.h>
+#include <machine/armreg.h>
#include <stdlib.h>
@@ -41,6 +42,8 @@ __FBSDID("$FreeBSD$");
extern char kernel_start[];
extern char kernel_end[];
+extern void *_end;
+
void __start(void);
#define GZ_HEAD 0xa
@@ -50,7 +53,7 @@ void __start(void);
#elif defined(CPU_ARM8)
#define cpu_idcache_wbinv_all arm8_cache_purgeID
#elif defined(CPU_ARM9)
-#define cpu_idcache_wbinv_all arm9_dcache_wbinv_all
+#define cpu_idcache_wbinv_all arm9_idcache_wbinv_all
#elif defined(CPU_ARM10)
#define cpu_idcache_wbinv_all arm10_idcache_wbinv_all
#elif defined(CPU_SA110) || defined(CPU_SA1110) || defined(CPU_SA1100) || \
@@ -60,8 +63,35 @@ void __start(void);
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
#define cpu_idcache_wbinv_all xscale_cache_purgeID
#endif
-int arm_pdcache_line_size = 32;
+
+#ifdef KZIP
+int arm_picache_size;
+int arm_picache_line_size;
+int arm_picache_ways;
+
+int arm_pdcache_size; /* and unified */
+int arm_pdcache_line_size = 32;
+int arm_pdcache_ways;
+
+int arm_pcache_type;
+int arm_pcache_unified;
+
+int arm_dcache_align;
+int arm_dcache_align_mask;
+
+/* Additional cache information local to this file. Log2 of some of the
+ above numbers. */
+static int arm_dcache_l2_nsets;
+static int arm_dcache_l2_assoc;
+static int arm_dcache_l2_linesize;
+
+
int block_userspace_access = 0;
+extern int arm9_dcache_sets_inc;
+extern int arm9_dcache_sets_max;
+extern int arm9_dcache_index_max;
+extern int arm9_dcache_index_inc;
+#endif
static __inline void *
memcpy(void *dst, const void *src, int len)
@@ -107,13 +137,18 @@ _start(void)
{
int physaddr = KERNPHYSADDR;
int tmp1;
+ unsigned int sp = (unsigned int)&_end;
+#ifdef KZIP
+ sp += KERNSIZE + 0x100;
+ sp &= ~(L1_TABLE_SIZE - 1);
+ sp += 2 * L1_TABLE_SIZE;
+#endif
+ sp += 1024 * 1024; /* Should be enough for a stack */
__asm __volatile("adr %0, 2f\n"
"bic %0, %0, #0xff000000\n"
- "bic sp, sp, #0xff000000\n"
"and %1, %1, #0xff000000\n"
"orr %0, %0, %1\n"
- "orr sp, sp, %1\n"
"mrc p15, 0, %1, c1, c0, 0\n"
"bic %1, %1, #1\n" /* Disable MMU */
"orr %1, %1, #(4 | 8)\n" /* Add DC enable,
@@ -127,11 +162,92 @@ _start(void)
"nop\n"
"mov pc, %0\n"
"2: nop\n"
- : "=r" (tmp1), "+r" (physaddr));
+ "mov sp, %2\n"
+ : "=r" (tmp1), "+r" (physaddr), "+r" (sp));
__start();
}
#ifdef KZIP
+static void
+get_cachetype_cp15()
+{
+ u_int ctype, isize, dsize;
+ u_int multiplier;
+
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
+ : "=r" (ctype));
+
+ /*
+ * ...and thus spake the ARM ARM:
+ *
+ * If an <opcode2> value corresponding to an unimplemented or
+ * reserved ID register is encountered, the System Control
+ * processor returns the value of the main ID register.
+ */
+ if (ctype == cpufunc_id())
+ goto out;
+
+ if ((ctype & CPU_CT_S) == 0)
+ arm_pcache_unified = 1;
+
+ /*
+ * If you want to know how this code works, go read the ARM ARM.
+ */
+
+ arm_pcache_type = CPU_CT_CTYPE(ctype);
+ if (arm_pcache_unified == 0) {
+ isize = CPU_CT_ISIZE(ctype);
+ multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
+ if (isize & CPU_CT_xSIZE_M)
+ arm_picache_line_size = 0; /* not present */
+ else
+ arm_picache_ways = 1;
+ } else {
+ arm_picache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(isize) - 1);
+ }
+ arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
+ }
+
+ dsize = CPU_CT_DSIZE(ctype);
+ multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
+ if (dsize & CPU_CT_xSIZE_M)
+ arm_pdcache_line_size = 0; /* not present */
+ else
+ arm_pdcache_ways = 1;
+ } else {
+ arm_pdcache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(dsize) - 1);
+ }
+ arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
+
+ arm_dcache_align = arm_pdcache_line_size;
+
+ arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
+ arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
+ arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
+ CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
+ out:
+ arm_dcache_align_mask = arm_dcache_align - 1;
+}
+
+static void
+arm9_setup(void)
+{
+
+ get_cachetype_cp15();
+ arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
+ arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
+ arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
+ arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
+ arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
+}
+
+
static unsigned char *orig_input, *i_input, *i_output;
@@ -354,7 +470,6 @@ load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end,
extern char func_end[];
-extern void *_end;
#define PMAP_DOMAIN_KERNEL 15 /*
* Just define it instead of including the
@@ -404,6 +519,7 @@ __start(void)
void *curaddr;
void *dst, *altdst;
char *kernel = (char *)&kernel_start;
+ int sp;
__asm __volatile("mov %0, pc" :
"=r" (curaddr));
@@ -413,6 +529,11 @@ __start(void)
int pt_addr = (((int)&_end + KERNSIZE + 0x100) &
~(L1_TABLE_SIZE - 1)) + L1_TABLE_SIZE;
+#ifdef CPU_ARM9
+ /* So that idcache_wbinv works; */
+ if ((cpufunc_id() & 0x0000f000) == 0x00009000)
+ arm9_setup();
+#endif
setup_pagetables(pt_addr, (vm_paddr_t)curaddr,
(vm_paddr_t)curaddr + 0x10000000);
/* Gzipped kernel */
@@ -433,10 +554,10 @@ __start(void)
dst = 4 + load_kernel((unsigned int)&kernel_start,
(unsigned int)curaddr,
(unsigned int)&func_end, 0);
+ sp = (vm_offset_t)dst + 4096;
+ dst = (void *)sp;
memcpy((void *)dst, (void *)&load_kernel, (unsigned int)&func_end -
(unsigned int)&load_kernel);
- ((void (*)())dst)((unsigned int)kernel,
- (unsigned int)curaddr,
- dst + (unsigned int)(&func_end) -
- (unsigned int)(&load_kernel), 1);
+ do_call(dst, kernel, dst + (unsigned int)(&func_end) -
+ (unsigned int)(&load_kernel), sp);
}
diff --git a/sys/arm/arm/inckern.S b/sys/arm/arm/inckern.S
index 8610196..bb0ec75 100644
--- a/sys/arm/arm/inckern.S
+++ b/sys/arm/arm/inckern.S
@@ -26,6 +26,14 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$")
+ENTRY(do_call)
+ mov r6, r0
+ mov r0, r1
+ ldr r1, =0xfff00000
+ and r1, pc, r1
+ mov sp, r3
+ mov r3, #1
+ mov pc, r6
.section ".real_kernel","aw"
.globl kernel_start;
kernel_start:
diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm
index 9a8ea46..db02b3c 100644
--- a/sys/conf/Makefile.arm
+++ b/sys/conf/Makefile.arm
@@ -62,7 +62,7 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M\
FILES_CPU_FUNC = $S/$M/$M/cpufunc_asm_arm7tdmi.S \
$S/$M/$M/cpufunc_asm_arm8.S $S/$M/$M/cpufunc_asm_arm9.S \
$S/$M/$M/cpufunc_asm_sa1.S $S/$M/$M/cpufunc_asm_arm10.S \
- $S/$M/$M/cpufunc_asm_xscale.S
+ $S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S
trampoline: ${KERNEL_KO}.tramp
${KERNEL_KO}.tramp: ${KERNEL_KO}
echo "#define KERNNAME \"${KERNEL_KO}.tmp\"" >opt_kernname.h
@@ -71,6 +71,8 @@ ${KERNEL_KO}.tramp: ${KERNEL_KO}
ldscript.$M.tramp.noheader
${OBJCOPY} --strip-symbol '$$d' --strip-symbol '$$a' \
-g --strip-symbol '$$t' ${FULLKERNEL} ${KERNEL_KO}.tmp
+ eval $$(stat -s ${KERNEL_KO}.tmp) && \
+ echo "#define KERNSIZE $$st_size" >>opt_kernname.h
${CC} -O -nostdlib -I. -Xlinker -T -Xlinker ldscript.$M.tramp \
$S/$M/$M/elf_trampoline.c $S/$M/$M/inckern.S -o ${KERNEL_KO}.tramp
${CC} -O -nostdlib -I. -Xlinker -T -Xlinker ldscript.$M.tramp.noheader \
OpenPOWER on IntegriCloud