/* SPDX-License-Identifier: GPL-2.0-only */ /* * Early kernel startup code for Hexagon * * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*/
__INIT
ENTRY(stext) /* * VMM will already have set up true vector page, MMU, etc. * To set up initial kernel identity map, we have to pass * the VMM a pointer to some canonical page tables. In * this implementation, we're assuming that we've got * them precompiled. Generate value in R24, as we'll need * it again shortly.
*/
r24.L = #LO(swapper_pg_dir)
r24.H = #HI(swapper_pg_dir)
/* * Symbol is kernel segment address, but we need * the logical/physical address.
*/
r25 = pc;
r2.h = #0xffc0;
r2.l = #0x0000;
r25 = and(r2,r25); /* R25 holds PHYS_OFFSET now */
r1.h = #HI(PAGE_OFFSET);
r1.l = #LO(PAGE_OFFSET);
r24 = sub(r24,r1); /* swapper_pg_dir - PAGE_OFFSET */
r24 = add(r24,r25); /* + PHYS_OFFSET */
r0 = r24; /* aka __pa(swapper_pg_dir) */
/* * Initialize page dir to make the virtual and physical * addresses where the kernel was loaded be identical. * Done in 4MB chunks.
*/
#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
| __HEXAGON_C_WB_L2 << 6 \
| __HVM_PDE_S_4MB)
/* * Get number of VA=PA entries; only really needed for jump * to hyperspace; gets blown away immediately after
*/
/* * The subroutine wrapper around the virtual instruction touches * no memory, so we should be able to use it even here. * Note that in this version, R1 and R2 get "clobbered"; see * vm_ops.S
*/
r1 = #VM_TRANS_TYPE_TABLE
call __vmnewmap;
/* Go ahead and install the trap0 return so angel calls work */
r0.h = #hi(_K_provisional_vec)
r0.l = #lo(_K_provisional_vec)
call __vmsetvec
/* * OK, at this point we should start to be much more careful, * we're going to enter C code and start touching memory * in all sorts of places. * This means: * SGP needs to be OK * Need to lock shared resources * A bunch of other things that will cause * all kinds of painful bugs
*/
/* * Stack pointer should be pointed at the init task's * thread stack, which should have been declared in arch/init_task.c. * So uhhhhh... * It's accessible via the init_thread_union, which is a union * of a thread_info struct and a stack; of course, the top * of the stack is not for you. The end of the stack * is simply init_thread_union + THREAD_SIZE.
*/
/* initialize the register used to point to current_thread_info */ /* Fixme: THREADINFO_REG can't be R2 because of that memset thing. */
{r29 = add(r29,r0); THREADINFO_REG = r29; }
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.