diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1994-12-01 08:00:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1994-12-01 08:00:00 +0000 |
commit | 90ecc248e200fee448001248dde0ca540dd3ef64 (patch) | |
tree | a3fe89494ce63b4835f0f9cf5c45e74cde88252b /arch/mips/boot | |
parent | 1513ff9b7899ab588401c89db0e99903dbf5f886 (diff) |
Import of Linux/MIPS 1.1.68
Diffstat (limited to 'arch/mips/boot')
-rw-r--r-- | arch/mips/boot/head.S | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/arch/mips/boot/head.S b/arch/mips/boot/head.S new file mode 100644 index 000000000..73e9d2cf9 --- /dev/null +++ b/arch/mips/boot/head.S @@ -0,0 +1,387 @@ +/* + * mips/head.S + * + * Copyright (C) 1994 Ralf Baechle + * + * Head.S contains the MIPS 32-bit startup code. + */ + +/* + * prevent prototypes from being imported + */ +#define __ASSEMBLY__ + +#include <asm/segment.h> +#include <asm/cachectl.h> +#include <asm/mipsregs.h> +#include <asm/mipsconfig.h> +#include <asm/stackframe.h> +#include <asm/regdef.h> +#include <linux/tasks.h> + + + .globl _empty_bad_page + .globl _empty_bad_page_table + .globl _invalid_pg_table + .globl _empty_zero_page + .globl _tmp_floppy_area + .globl _floppy_track_buffer + .globl _swapper_pg_dir + + .set noreorder + + .text +/* + * This is space for the interrupt handlers. + * They are located at virtual address 0x80000000 (physical 0x0) + */ + /* + * TLB refill, EXL == 0 + */ +except_vec0: + .set noreorder + .set noat + /* + * This TLB-refill handler is supposed never to cause + * another tlb-refill exception. Unmapped pages will + * cause another type of exception. + */ + dmfc0 k0,CP0_CONTEXT + dsrl k0,k0,1 + lwu k0,(k1) + lwu k1,4(k1) + dmtc0 k0,CP0_ENTRYLO0 + dmtc0 k0,CP0_ENTRYLO1 + tlbwr + eret + + /* + * XTLB refill, EXL == 0 (X == 64-bit TLB) + */ + .org except_vec0+0x80 +except_vec1: + /* + * Not used yet... + */ + eret + + /* + * Cache Error + */ + .org except_vec1+0x80 +except_vec2: + /* + * Not used yet... + */ + eret + + /* + * General exception vector. + */ + .org except_vec2+0x80 +except_vec3: + SAVE_ALL + mfc0 t0,CP0_STATUS + ori t0,t0,0x1f + xori t0,t0,0x1f + mtc0 t0,CP0_STATUS + .set at + la k0,_exception_handlers + mfc0 k1,CP0_CAUSE + andi k1,k1,0x7c + addu k0,k0,k1 + lw k0,(k0) + FILL_LDS + jr k0 + nop + + +/******************************************************************************/ + + /* + * The following data is expected to be at certain absolute + * addresses, which are hardwired in + * include/asm-mips/mipsconfig.h + * If the following offset is to short, the assembler will + * break with an assertion failure. You then will have to + * increase it and to fix the address in + * include/asm-mips/mipsconfig.h + */ + + .org except_vec3+0x100 + .globl _kernelsp +_kernelsp: .word 0 + +kernel_entry: + +/* + * Flush the TLB + */ + dmtc0 zero,CP0_ENTRYHI + dmtc0 zero,CP0_ENTRYLO0 + dmtc0 zero,CP0_ENTRYLO1 + li t0,NUMBER_OF_TLB_ENTRIES-1 +1: mtc0 t0,CP0_INDEX + tlbwi + bne zero,t0,1b + subu t0,t0,1 + +/* + * Initialize memory management. + * Wire mapping for port i/o space 0xe0000000 -> 0x9000000900000000 + */ + li t0,3 + mtc0 t0,CP0_WIRED + li t0,PM_64K + mtc0 t0,CP0_PAGEMASK + la t3,map0 + ld t1,0(t3) + ld t2,8(t3) + mtc0 zero,CP0_INDEX + dmtc0 t1,CP0_ENTRYHI + dmtc0 t2,CP0_ENTRYLO0 + dmtc0 zero,CP0_ENTRYLO1 /* Invalid page */ + tlbwi + li t0,PM_1M + mtc0 t0,CP0_PAGEMASK + ld t1,16(t3) + ld t2,24(t3) + li t0,1 + mtc0 t0,CP0_INDEX + dmtc0 t1,CP0_ENTRYHI + dmtc0 t2,CP0_ENTRYLO0 + tlbwi + ld t1,32(t3) + ld t2,40(t3) + li t0,2 + mtc0 t0,CP0_INDEX + dmtc0 t1,CP0_ENTRYHI + dmtc0 t2,CP0_ENTRYLO0 + tlbwi + +/* + * We always use 4k pages. Therefore the PageMask register + * is expected to be setup for 4k pages. + */ + li t0,PM_4K + mtc0 t0,CP0_PAGEMASK + +/* + * Clear BSS first so that there are no surprises... + */ + la t0,__edata + la t1,__end + sw zero,(t0) +1: addiu t0,t0,4 + bnel t0,t1,1b + sw zero,(t0) + +/* + * Copy bootup parameters out of the way. First 2kB of + * _empty_zero_page is for boot parameters, second 2kB + * is for the command line. + */ +#if 0 + movl $0x90000,%esi + movl $_empty_zero_page,%edi + movl $512,%ecx + cld + rep + movsl + xorl %eax,%eax + movl $512,%ecx + rep + stosl + cmpw $(CL_MAGIC),CL_MAGIC_ADDR + jne 1f + movl $_empty_zero_page+2048,%edi + movzwl CL_OFFSET,%esi + addl $(CL_BASE_ADDR),%esi + movl $2048,%ecx + rep + movsb +#endif + + /* + * Preliminary stack... + */ + la sp,0x80700000 + sw sp,_kernelsp +6: + jal _start_kernel + nop + j 6b # main should never return here, but + # just in case, we know what happens. + +#if 0 +/* This is the default interrupt "handler" :-) */ +int_msg: + .asciz "Unknown interrupt\n" +.align 2 +ignore_int: + cld + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + pushl $int_msg + call _printk + popl %eax + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret +#endif + +#define CACHELINES 512 /* number of cachelines */ + +/* + * Flush instruction/data caches + * + * Parameters: a0 - starting address to flush + * a1 - size of area to be flushed + * a2 - which caches to be flushed + * + * FIXME: - ignores parameters + * - doesn't know about second level caches + */ + + .set noreorder + .globl _cacheflush + .text +_cacheflush: + /* + * Flush the instruction cache + */ + lui t0,0x8000 + li t1,CACHELINES-1 +1: cache 0,0(t0) + cache 0,32(t0) + cache 0,64(t0) + cache 0,96(t0) + cache 0,128(t0) + cache 0,160(t0) + cache 0,192(t0) + cache 0,224(t0) + cache 0,256(t0) + cache 0,288(t0) + cache 0,320(t0) + cache 0,352(t0) + cache 0,384(t0) + cache 0,416(t0) + cache 0,448(t0) + cache 0,480(t0) + addiu t0,t0,512 + bne zero,t1,1b + subu t1,t1,1 + /* + * Flush the data cache + */ + lui t0,0x8000 + li t1,CACHELINES-1 +1: cache 1,0(t0) + cache 1,32(t0) + cache 1,64(t0) + cache 1,96(t0) + cache 1,128(t0) + cache 1,160(t0) + cache 1,192(t0) + cache 1,224(t0) + cache 1,256(t0) + cache 1,288(t0) + cache 1,320(t0) + cache 1,352(t0) + cache 1,384(t0) + cache 1,416(t0) + cache 1,448(t0) + cache 1,480(t0) + addiu t0,t0,512 + bne zero,t1,1b + subu t1,t1,1 + + j ra + nop + + .globl _beep +_beep: lbu t0,0xe0000061 + xori t0,t0,3 + sb t0,0xe0000061 + jr ra + nop + +/* + * Instead of Intel's strage and unportable segment descriptor magic + * we difference user and kernel space by their address. + * Kernel space (== physical memory) is mapped at 0x80000000, + * User space is mapped at 0x0. + */ + + .data + + .globl _segment_fs + /* + * Inital wired mappings + */ +map0: .quad 0xc00000ffe0000000,0x24000017 + .quad 0xc00000ffe1000000,0x04000017 + .quad 0xc00000ffe2000000,0x04020017 + +/* + * page 0 is made non-existent, so that kernel NULL pointer references get + * caught. Thus the swapper page directory has been moved to 0x1000 + * + * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte, + * with the introduction of the compressed boot code. Theoretically, + * the original design of overlaying the startup code with the swapper + * page directory is still possible --- it would reduce the size of the kernel + * by 2-3k. This would be a good thing to do at some point..... + */ + .text + + .org 0x1000 +_swapper_pg_dir: +/* + * The page tables are initialized to only 4MB here - the final page + * tables are set up later depending on memory size. + */ + .org 0x2000 +_pg0: + + .org 0x3000 +_empty_bad_page: + + .org 0x4000 +_empty_bad_page_table: + + .org 0x5000 +_invalid_pg_table: + + .org 0x6000 +_empty_zero_page: + + .org 0x7000 + +/* + * tmp_floppy_area is used by the floppy-driver when DMA cannot + * reach to a buffer-block. It needs to be aligned, so that it isn't + * on a 64kB border. + */ +_tmp_floppy_area: .fill 1024,1,0 +/* + * floppy_track_buffer is used to buffer one track of floppy data: it + * has to be separate from the tmp_floppy area, as otherwise a single- + * sector read/write can mess it up. It can contain one full cylinder (sic) of + * data (36*2*512 bytes). + */ +_floppy_track_buffer: .fill 512*2*36,1,0 + +_segment_fs: .word KERNEL_DS |