| /* | |
| * This file is subject to the terms and conditions of the GNU General Public | |
| * License. See the file "COPYING" in the main directory of this archive | |
| * for more details. | |
| * | |
| * Copyright (C) 1994, 1995 Waldorf Electronics | |
| * Written by Ralf Baechle and Andreas Busse | |
| * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 Ralf Baechle | |
| * Copyright (C) 1996 Paul M. Antoine | |
| * Modified for DECStation and hence R3000 support by Paul M. Antoine | |
| * Further modifications by David S. Miller and Harald Koerfgen | |
| * Copyright (C) 1999 Silicon Graphics, Inc. | |
| * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com | |
| * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | |
| */ | |
| #include <linux/config.h> | |
| #include <linux/init.h> | |
| #include <linux/threads.h> | |
| #include <asm/asm.h> | |
| #include <asm/regdef.h> | |
| #include <asm/page.h> | |
| #include <asm/mipsregs.h> | |
| #include <asm/stackframe.h> | |
| #include <kernel-entry-init.h> | |
| .macro ARC64_TWIDDLE_PC | |
| #if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL) | |
| /* We get launched at a XKPHYS address but the kernel is linked to | |
| run at a KSEG0 address, so jump there. */ | |
| PTR_LA t0, \@f | |
| jr t0 | |
| \@: | |
| #endif | |
| .endm | |
| /* | |
| * inputs are the text nasid in t1, data nasid in t2. | |
| */ | |
| .macro MAPPED_KERNEL_SETUP_TLB | |
| #ifdef CONFIG_MAPPED_KERNEL | |
| /* | |
| * This needs to read the nasid - assume 0 for now. | |
| * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0, | |
| * 0+DVG in tlblo_1. | |
| */ | |
| dli t0, 0xffffffffc0000000 | |
| dmtc0 t0, CP0_ENTRYHI | |
| li t0, 0x1c000 # Offset of text into node memory | |
| dsll t1, NASID_SHFT # Shift text nasid into place | |
| dsll t2, NASID_SHFT # Same for data nasid | |
| or t1, t1, t0 # Physical load address of kernel text | |
| or t2, t2, t0 # Physical load address of kernel data | |
| dsrl t1, 12 # 4K pfn | |
| dsrl t2, 12 # 4K pfn | |
| dsll t1, 6 # Get pfn into place | |
| dsll t2, 6 # Get pfn into place | |
| li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) | |
| or t0, t0, t1 | |
| mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr | |
| li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) | |
| or t0, t0, t2 | |
| mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr | |
| li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M | |
| mtc0 t0, CP0_PAGEMASK | |
| li t0, 0 # KMAP_INX | |
| mtc0 t0, CP0_INDEX | |
| li t0, 1 | |
| mtc0 t0, CP0_WIRED | |
| tlbwi | |
| #else | |
| mtc0 zero, CP0_WIRED | |
| #endif | |
| .endm | |
| /* | |
| * For the moment disable interrupts, mark the kernel mode and | |
| * set ST0_KX so that the CPU does not spit fire when using | |
| * 64-bit addresses. A full initialization of the CPU's status | |
| * register is done later in per_cpu_trap_init(). | |
| */ | |
| .macro setup_c0_status set clr | |
| .set push | |
| mfc0 t0, CP0_STATUS | |
| or t0, ST0_CU0|\set|0x1f|\clr | |
| xor t0, 0x1f|\clr | |
| mtc0 t0, CP0_STATUS | |
| .set noreorder | |
| sll zero,3 # ehb | |
| .set pop | |
| .endm | |
| .macro setup_c0_status_pri | |
| #ifdef CONFIG_64BIT | |
| setup_c0_status ST0_KX 0 | |
| #else | |
| setup_c0_status 0 0 | |
| #endif | |
| .endm | |
| .macro setup_c0_status_sec | |
| #ifdef CONFIG_64BIT | |
| setup_c0_status ST0_KX ST0_BEV | |
| #else | |
| setup_c0_status 0 ST0_BEV | |
| #endif | |
| .endm | |
| /* | |
| * Reserved space for exception handlers. | |
| * Necessary for machines which link their kernels at KSEG0. | |
| */ | |
| .fill 0x400 | |
| EXPORT(stext) # used for profiling | |
| EXPORT(_stext) | |
| #if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM) | |
| /* | |
| * Give us a fighting chance of running if execution beings at the | |
| * kernel load address. This is needed because this platform does | |
| * not have a ELF loader yet. | |
| */ | |
| j kernel_entry | |
| #endif | |
| __INIT | |
| NESTED(kernel_entry, 16, sp) # kernel entry point | |
| kernel_entry_setup # cpu specific setup | |
| setup_c0_status_pri | |
| ARC64_TWIDDLE_PC | |
| PTR_LA t0, __bss_start # clear .bss | |
| LONG_S zero, (t0) | |
| PTR_LA t1, __bss_stop - LONGSIZE | |
| 1: | |
| PTR_ADDIU t0, LONGSIZE | |
| LONG_S zero, (t0) | |
| bne t0, t1, 1b | |
| LONG_S a0, fw_arg0 # firmware arguments | |
| LONG_S a1, fw_arg1 | |
| LONG_S a2, fw_arg2 | |
| LONG_S a3, fw_arg3 | |
| MTC0 zero, CP0_CONTEXT # clear context register | |
| PTR_LA $28, init_thread_union | |
| PTR_ADDIU sp, $28, _THREAD_SIZE - 32 | |
| set_saved_sp sp, t0, t1 | |
| PTR_SUBU sp, 4 * SZREG # init stack pointer | |
| j start_kernel | |
| END(kernel_entry) | |
| #ifdef CONFIG_QEMU | |
| __INIT | |
| #endif | |
| #ifdef CONFIG_SMP | |
| /* | |
| * SMP slave cpus entry point. Board specific code for bootstrap calls this | |
| * function after setting up the stack and gp registers. | |
| */ | |
| NESTED(smp_bootstrap, 16, sp) | |
| setup_c0_status_sec | |
| smp_slave_setup | |
| j start_secondary | |
| END(smp_bootstrap) | |
| #endif /* CONFIG_SMP */ | |
| __FINIT | |
| .comm kernelsp, NR_CPUS * 8, 8 | |
| .comm pgd_current, NR_CPUS * 8, 8 | |
| .comm fw_arg0, SZREG, SZREG # firmware arguments | |
| .comm fw_arg1, SZREG, SZREG | |
| .comm fw_arg2, SZREG, SZREG | |
| .comm fw_arg3, SZREG, SZREG | |
| .macro page name, order | |
| .comm \name, (_PAGE_SIZE << \order), (_PAGE_SIZE << \order) | |
| .endm | |
| /* | |
| * On 64-bit we've got three-level pagetables with a slightly | |
| * different layout ... | |
| */ | |
| page swapper_pg_dir, _PGD_ORDER | |
| #ifdef CONFIG_64BIT | |
| page invalid_pmd_table, _PMD_ORDER | |
| #endif | |
| page invalid_pte_table, _PTE_ORDER |