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.
This commit is contained in:
parent
9464ffd0a4
commit
ee8ecea34b
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user