1 /* SPDX-License-Identifier: GPL-2.0-only */ << 2 /* 1 /* 3 * Early kernel startup code for Hexagon !! 2 * This file is subject to the terms and conditions of the GNU General Public >> 3 * License. See the file "COPYING" in the main directory of this archive >> 4 * for more details. 4 * 5 * 5 * Copyright (c) 2010-2013, The Linux Foundati !! 6 * Copyright (C) 1994, 1995 Waldorf Electronics >> 7 * Written by Ralf Baechle and Andreas Busse >> 8 * Copyright (C) 1994 - 99, 2003, 06 Ralf Baechle >> 9 * Copyright (C) 1996 Paul M. Antoine >> 10 * Modified for DECStation and hence R3000 support by Paul M. Antoine >> 11 * Further modifications by David S. Miller and Harald Koerfgen >> 12 * Copyright (C) 1999 Silicon Graphics, Inc. >> 13 * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com >> 14 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. 6 */ 15 */ 7 << 8 #include <linux/linkage.h> << 9 #include <linux/init.h> 16 #include <linux/init.h> 10 #include <asm/asm-offsets.h> !! 17 #include <linux/threads.h> 11 #include <asm/mem-layout.h> << 12 #include <asm/vm_mmu.h> << 13 #include <asm/page.h> << 14 #include <asm/hexagon_vm.h> << 15 18 16 #define SEGTABLE_ENTRIES #0x0e0 !! 19 #include <asm/addrspace.h> >> 20 #include <asm/asm.h> >> 21 #include <asm/asmmacro.h> >> 22 #include <asm/irqflags.h> >> 23 #include <asm/regdef.h> >> 24 #include <asm/mipsregs.h> >> 25 #include <asm/stackframe.h> >> 26 >> 27 #include <kernel-entry-init.h> >> 28 >> 29 /* >> 30 * For the moment disable interrupts, mark the kernel mode and >> 31 * set ST0_KX so that the CPU does not spit fire when using >> 32 * 64-bit addresses. A full initialization of the CPU's status >> 33 * register is done later in per_cpu_trap_init(). >> 34 */ >> 35 .macro setup_c0_status set clr >> 36 .set push >> 37 mfc0 t0, CP0_STATUS >> 38 or t0, ST0_KERNEL_CUMASK|\set|0x1f|\clr >> 39 xor t0, 0x1f|\clr >> 40 mtc0 t0, CP0_STATUS >> 41 .set noreorder >> 42 sll zero,3 # ehb >> 43 .set pop >> 44 .endm >> 45 >> 46 .macro setup_c0_status_pri >> 47 #ifdef CONFIG_64BIT >> 48 setup_c0_status ST0_KX 0 >> 49 #else >> 50 setup_c0_status 0 0 >> 51 #endif >> 52 .endm 17 53 18 __INIT !! 54 .macro setup_c0_status_sec 19 ENTRY(stext) !! 55 #ifdef CONFIG_64BIT 20 /* !! 56 setup_c0_status ST0_KX ST0_BEV 21 * VMM will already have set up true v !! 57 #else 22 * To set up initial kernel identity m !! 58 setup_c0_status 0 ST0_BEV 23 * the VMM a pointer to some canonical !! 59 #endif 24 * this implementation, we're assuming !! 60 .endm 25 * them precompiled. Generate value in << 26 * it again shortly. << 27 */ << 28 r24.L = #LO(swapper_pg_dir) << 29 r24.H = #HI(swapper_pg_dir) << 30 61 >> 62 #ifndef CONFIG_NO_EXCEPT_FILL 31 /* 63 /* 32 * Symbol is kernel segment address, b !! 64 * Reserved space for exception handlers. 33 * the logical/physical address. !! 65 * Necessary for machines which link their kernels at KSEG0. 34 */ 66 */ 35 r25 = pc; !! 67 .fill 0x400 36 r2.h = #0xffc0; !! 68 #endif 37 r2.l = #0x0000; << 38 r25 = and(r2,r25); /* R25 holds << 39 r1.h = #HI(PAGE_OFFSET); << 40 r1.l = #LO(PAGE_OFFSET); << 41 r24 = sub(r24,r1); /* swapper_pg_ << 42 r24 = add(r24,r25); /* + PHYS_OFFS << 43 << 44 r0 = r24; /* aka __pa(swapper_pg_dir) << 45 69 46 /* !! 70 EXPORT(_stext) 47 * Initialize page dir to make the vir << 48 * addresses where the kernel was load << 49 * Done in 4MB chunks. << 50 */ << 51 #define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | << 52 | __HEXAGON_C_WB_L2 << 6 << 53 | __HVM_PDE_S_4MB) << 54 71 >> 72 #ifdef CONFIG_BOOT_RAW 55 /* 73 /* 56 * Get number of VA=PA entries; only r !! 74 * Give us a fighting chance of running if execution beings at the 57 * to hyperspace; gets blown away imme !! 75 * kernel load address. This is needed because this platform does >> 76 * not have a ELF loader yet. 58 */ 77 */ >> 78 FEXPORT(__kernel_entry) >> 79 j kernel_entry >> 80 #endif /* CONFIG_BOOT_RAW */ 59 81 60 { !! 82 __REF 61 r1.l = #LO(_end); << 62 r2.l = #LO(stext); << 63 r3 = #1; << 64 } << 65 { << 66 r1.h = #HI(_end); << 67 r2.h = #HI(stext); << 68 r3 = asl(r3, #22); << 69 } << 70 { << 71 r1 = sub(r1, r2); << 72 r3 = add(r3, #-1); << 73 } /* r1 = _end - stext */ << 74 r1 = add(r1, r3); /* + (4M-1) */ << 75 r26 = lsr(r1, #22); /* / 4M = # of en << 76 << 77 r1 = r25; << 78 r2.h = #0xffc0; << 79 r2.l = #0x0000; /* round back << 80 r1 = and(r1,r2); << 81 r2 = lsr(r1, #22) /* 4MB page nu << 82 r2 = asl(r2, #2) /* times sizeo << 83 r0 = add(r0,r2) /* r0 = addres << 84 r2 = #PTE_BITS << 85 r1 = add(r1,r2) /* r1 = 4MB PT << 86 r2.h = #0x0040 << 87 r2.l = #0x0000 /* 4MB increme << 88 loop0(1f,r26); << 89 1: << 90 memw(r0 ++ #4) = r1 << 91 { r1 = add(r1, r2); } :endloop0 << 92 << 93 /* Also need to overwrite the initial << 94 /* PAGE_OFFSET >> (4MB shift - 4 byte << 95 R1.H = #HI(PAGE_OFFSET >> (22 - 2)) << 96 R1.L = #LO(PAGE_OFFSET >> (22 - 2)) << 97 << 98 r0 = add(r1, r24); /* advance to << 99 r1 = r25; << 100 r2.h = #0xffc0; << 101 r2.l = #0x0000; /* round back << 102 r1 = and(r1,r2); /* for huge pa << 103 r2 = #PTE_BITS << 104 r1 = add(r1,r2); << 105 r2.h = #0x0040 << 106 r2.l = #0x0000 /* 4MB increme << 107 83 108 loop0(1f,SEGTABLE_ENTRIES); !! 84 NESTED(kernel_entry, 16, sp) # kernel entry point 109 1: << 110 memw(r0 ++ #4) = r1; << 111 { r1 = add(r1,r2); } :endloop0 << 112 85 113 r0 = r24; !! 86 kernel_entry_setup # cpu specific setup 114 87 115 /* !! 88 setup_c0_status_pri 116 * The subroutine wrapper around the v << 117 * no memory, so we should be able to << 118 * Note that in this version, R1 and R << 119 * vm_ops.S << 120 */ << 121 r1 = #VM_TRANS_TYPE_TABLE << 122 call __vmnewmap; << 123 89 124 /* Jump into virtual address range. !! 90 /* We might not get launched at the address the kernel is linked to, 125 !! 91 so we jump there. */ 126 r31.h = #hi(__head_s_vaddr_target) !! 92 PTR_LA t0, 0f 127 r31.l = #lo(__head_s_vaddr_target) !! 93 jr t0 128 jumpr r31 !! 94 0: 129 << 130 /* Insert trippy space effects. */ << 131 << 132 __head_s_vaddr_target: << 133 /* << 134 * Tear down VA=PA translation now tha << 135 * in kernel virtual space. << 136 */ << 137 r0 = #__HVM_PDE_S_INVALID << 138 << 139 r1.h = #0xffc0; << 140 r1.l = #0x0000; << 141 r2 = r25; /* phys_offset << 142 r2 = and(r1,r2); << 143 << 144 r1.l = #lo(swapper_pg_dir) << 145 r1.h = #hi(swapper_pg_dir) << 146 r2 = lsr(r2, #22) /* 4MB page nu << 147 r2 = asl(r2, #2) /* times sizeo << 148 r1 = add(r1,r2); << 149 loop0(1f,r26) << 150 95 >> 96 PTR_LA t0, __bss_start # clear .bss >> 97 LONG_S zero, (t0) >> 98 PTR_LA t1, __bss_stop - LONGSIZE 151 1: 99 1: 152 { !! 100 PTR_ADDIU t0, LONGSIZE 153 memw(R1 ++ #4) = R0 !! 101 LONG_S zero, (t0) 154 }:endloop0 !! 102 bne t0, t1, 1b 155 !! 103 156 r0 = r24 !! 104 LONG_S a0, fw_arg0 # firmware arguments 157 r1 = #VM_TRANS_TYPE_TABLE !! 105 LONG_S a1, fw_arg1 158 call __vmnewmap !! 106 LONG_S a2, fw_arg2 159 !! 107 LONG_S a3, fw_arg3 160 /* Go ahead and install the trap0 ret !! 108 161 r0.h = #hi(_K_provisional_vec) !! 109 MTC0 zero, CP0_CONTEXT # clear context register 162 r0.l = #lo(_K_provisional_vec) !! 110 #ifdef CONFIG_64BIT 163 call __vmsetvec !! 111 MTC0 zero, CP0_XCONTEXT 164 << 165 /* << 166 * OK, at this point we should start t << 167 * we're going to enter C code and sta << 168 * in all sorts of places. << 169 * This means: << 170 * SGP needs to be OK << 171 * Need to lock shared resources << 172 * A bunch of other things that w << 173 * all kinds of painful bugs << 174 */ << 175 << 176 /* << 177 * Stack pointer should be pointed at << 178 * thread stack, which should have bee << 179 * So uhhhhh... << 180 * It's accessible via the init_thread << 181 * of a thread_info struct and a stack << 182 * of the stack is not for you. The e << 183 * is simply init_thread_union + THREA << 184 */ << 185 << 186 {r29.H = #HI(init_thread_union); r0.H << 187 {r29.L = #LO(init_thread_union); r0.L << 188 << 189 /* initialize the register used to po << 190 /* Fixme: THREADINFO_REG can't be R2 << 191 {r29 = add(r29,r0); THREADINFO_REG = r << 192 << 193 /* Hack: zero bss; */ << 194 { r0.L = #LO(__bss_start); r1 = #0; r << 195 { r0.H = #HI(__bss_start); r << 196 << 197 r2 = sub(r2,r0); << 198 call memset; << 199 << 200 /* Set PHYS_OFFSET; should be in R25 << 201 #ifdef CONFIG_HEXAGON_PHYS_OFFSET << 202 r0.l = #LO(__phys_offset); << 203 r0.h = #HI(__phys_offset); << 204 memw(r0) = r25; << 205 #endif 112 #endif >> 113 PTR_LA $28, init_thread_union >> 114 /* Set the SP after an empty pt_regs. */ >> 115 PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE >> 116 PTR_ADDU sp, $28 >> 117 back_to_back_c0_hazard >> 118 set_saved_sp sp, t0, t1 >> 119 PTR_SUBU sp, 4 * SZREG # init stack pointer >> 120 >> 121 #ifdef CONFIG_RELOCATABLE >> 122 /* Copy kernel and apply the relocations */ >> 123 jal relocate_kernel >> 124 >> 125 /* Repoint the sp into the new kernel image */ >> 126 PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE >> 127 PTR_ADDU sp, $28 >> 128 set_saved_sp sp, t0, t1 >> 129 PTR_SUBU sp, 4 * SZREG # init stack pointer >> 130 >> 131 /* >> 132 * relocate_kernel returns the entry point either >> 133 * in the relocated kernel or the original if for >> 134 * some reason relocation failed - jump there now >> 135 * with instruction hazard barrier because of the >> 136 * newly sync'd icache. >> 137 */ >> 138 jr.hb v0 >> 139 #else /* !CONFIG_RELOCATABLE */ >> 140 j start_kernel >> 141 #endif /* !CONFIG_RELOCATABLE */ >> 142 END(kernel_entry) 206 143 207 /* Time to make the doughnuts. */ !! 144 #ifdef CONFIG_SMP 208 call start_kernel !! 145 /* 209 !! 146 * SMP slave cpus entry point. Board specific code for bootstrap calls this 210 /* !! 147 * function after setting up the stack and gp registers. 211 * Should not reach here. !! 148 */ 212 */ !! 149 NESTED(smp_bootstrap, 16, sp) 213 1: !! 150 smp_slave_setup 214 jump 1b !! 151 setup_c0_status_sec 215 !! 152 j start_secondary 216 .p2align PAGE_SHIFT !! 153 END(smp_bootstrap) 217 ENTRY(external_cmdline_buffer) !! 154 #endif /* CONFIG_SMP */ 218 .fill _PAGE_SIZE,1,0 << 219 << 220 .data << 221 .p2align PAGE_SHIFT << 222 ENTRY(empty_zero_page) << 223 .fill _PAGE_SIZE,1,0 <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.