diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1995-11-14 08:00:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1995-11-14 08:00:00 +0000 |
commit | e7c2a72e2680827d6a733931273a93461c0d8d1b (patch) | |
tree | c9abeda78ef7504062bb2e816bcf3e3c9d680112 /arch/mips/kernel/head.S | |
parent | ec6044459060a8c9ce7f64405c465d141898548c (diff) |
Import of Linux/MIPS 1.3.0
Diffstat (limited to 'arch/mips/kernel/head.S')
-rw-r--r-- | arch/mips/kernel/head.S | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S new file mode 100644 index 000000000..a2cb43de3 --- /dev/null +++ b/arch/mips/kernel/head.S @@ -0,0 +1,412 @@ +/* + * arch/mips/kernel/head.S + * + * Copyright (C) 1994, 1995 Waldorf Electronics + * Written by Ralf Baechle and Andreas Busse + * + * Head.S contains the MIPS exception handler and startup code. + */ +#include <linux/tasks.h> + +#include <asm/asm.h> +#include <asm/segment.h> +#include <asm/cachectl.h> +#include <asm/mipsregs.h> +#include <asm/mipsconfig.h> +#include <asm/stackframe.h> +#include <asm/bootinfo.h> + +#define PAGE_SIZE 0x1000 + +#define MODE_GLOBAL 0x0001 /* shared for all processes */ +#define MODE_ALIAS 0x0016 /* uncachable */ + + .text + .set mips3 +/* + * This is space for the interrupt handlers. + * They are located at virtual address KSEG[01] (physical 0x0) + */ + /* + * TLB refill, EXL == 0 + */ + .set noreorder + .set noat + LEAF(except_vec0) + dmfc0 k1,CP0_CONTEXT + dsra k1,1 + lwu k0,(k1) # May cause another exception + lwu k1,4(k1) + dsrl k0,6 # Convert to EntryLo format + dsrl k1,6 # Convert to EntryLo format + dmtc0 k0,CP0_ENTRYLO0 + dmtc0 k1,CP0_ENTRYLO1 + nop # Needed for R4[04]00 pipeline + tlbwr + nop # Needed for R4[04]00 pipeline + nop + nop + eret + /* + * Workaround for R4000 bug. For explanation see MIPS + * docs. Note that this that obscure that it wont almost + * never happen. Well, but Mips writes about it's bugs. + */ + nop + eret + END(except_vec0) + + /* + * XTLB refill, EXL == 0 + * Should never be reached + */ + .org except_vec0+0x80 + LEAF(except_vec1) + PANIC("XTLB Refill exception.\n") +1: j 1b + nop + END(except_vec1) + + /* + * Cache Error + */ + .org except_vec1+0x80 + LEAF(except_vec2) + /* + * Famous last words: unreached + */ + mfc0 a1,CP0_ERROREPC + PRINT("Cache error exception: c0_errorepc == %08x\n") +1: j 1b + nop + END(except_vec2) + + /* + * General exception vector. + */ + .org except_vec2+0x80 + NESTED(except_vec3, 0, sp) + .set noat + /* + * Register saving is delayed as long as we don't know + * which registers really need to be saved. + */ + mfc0 k1,CP0_CAUSE + la k0,exception_handlers + /* + * Next lines assumes that the used CPU type has max. + * 32 different types of exceptions. We might use this + * to implement software exceptions in the future. + */ + andi k1,0x7c + addu k0,k1 + lw k0,(k0) + NOP + jr k0 + nop + END(except_vec3) + .set at + +/******************************************************************************/ + +/* + * Kernel entry + */ + .set noreorder + NESTED(kernel_entry, 16, sp) + /* + * Clear BSS first so that there are no surprises... + */ + la t0,_edata + la t1,_end + sw zero,(t0) +1: addiu t0,4 + bnel t0,t1,1b + sw zero,(t0) + + /* + * Initialize low level part of memory management + */ + jal tlbflush + mtc0 zero,CP0_WIRED # delay slot + jal wire_mappings + nop + jal tlbflush + nop + + /* + * Stack for kernel and init + */ + la sp,init_user_stack+PAGE_SIZE-24 + la t0,init_kernel_stack+PAGE_SIZE + sw t0,kernelsp + + /* + * Disable coprocessors + */ + mfc0 t0,CP0_STATUS + li t1,~(ST0_CU0|ST0_CU1|ST0_CU2|ST0_CU3) + and t0,t1 + mtc0 t0,CP0_STATUS + +1: jal start_kernel + nop # delay slot + /* + * Main should never return here, but + * just in case, we know what happens. + */ + b 1b + nop # delay slot + END(kernel_entry) + +/* + * wire_mappings - used to map hardware registers + */ + LEAF(wire_mappings) + /* + * Get base address of map0 table for the + * the board we're running on + */ + la t0,boot_info + lw t1,OFFSET_BOOTINFO_MACHTYPE(t0) + la t0,map0table + sll t1,PTRLOG # machtype used as index + addu t0,t1 + lw t0,(t0) # get base address + + /* + * Get number of wired TLB entries and + * loop over selected map0 table. + */ + lw t1,(t0) # number of wired TLB entries + move t2,zero # TLB entry counter + addiu t3,t1,1 # wire one additional entry + beqz t1,2f # null, exit + mtc0 t3,CP0_WIRED # delay slot + addiu t0,8 +1: lw t4,24(t0) # PageMask + ld t5,0(t0) # entryHi + ld t6,8(t0) # entryLo0 + ld t7,16(t0) # entryLo1 + addiu t2,1 # increment ctr + mtc0 t2,CP0_INDEX # set TLB entry + mtc0 t4,CP0_PAGEMASK + dmtc0 t5,CP0_ENTRYHI + dmtc0 t6,CP0_ENTRYLO0 + dmtc0 t7,CP0_ENTRYLO1 + addiu t0,32 + bne t1,t2,1b # next TLB entry + tlbwi # delay slot + + /* + * We use only 4k pages. Therefore the PageMask register + * is expected to be setup for 4k pages. + */ +2: li t0,PM_4K + mtc0 t0,CP0_PAGEMASK + + /* + * Now map the pagetables + */ + mtc0 zero,CP0_INDEX + la t0,TLB_ROOT + dmtc0 t0,CP0_ENTRYHI + la t0,swapper_pg_dir-KSEG1 + srl t0,6 + ori t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid + dmtc0 t0,CP0_ENTRYLO0 + li t0,MODE_GLOBAL + dmtc0 t0,CP0_ENTRYLO1 + nop + tlbwi # delayed + + /* + * Load the context register with a value that allows + * it to be used as fast as possible in tlb exceptions. + * It is expected that this register's content will + * NEVER be changed. + */ + li t0,TLBMAP + dsll t0,1 + dmtc0 t0,CP0_CONTEXT + jr ra # delay slot + nop + END(wire_mappings) + +/* + * Just for debugging... + */ + .set noreorder + LEAF(beep) + lw t0,beepflag + nop + bnez t0,1f + lbu t0,0xe2000061 + xori t0,3 + sb t0,0xe2000061 + li t0,1 + sw t0,beepflag +1: jr ra + nop + END(beep) + + .bss +beepflag: .word 0 + .text + +/* + * Compute kernel code checksum to check kernel code against corruption + */ + LEAF(csum) + jal sys_cacheflush + move t8,ra # delay slot + li t0,KSEG1 + la t1,final + li t2,KSEG1 + or t0,t2 + or t1,t2 + move v0,zero +1: lw t2,(t0) + addiu t0,4 + bne t0,t1,1b + xor v0,t2 + jr t8 + nop + END(csum) +final: + + .data +/* + * Build an entry for table of wired entries + */ +#define MAPDATA(q1,q2,q3,w1) \ + .quad q1; \ + .quad q2; \ + .quad q3; \ + .word w1; \ + .word 0 + +/* + * Initial mapping tables for supported Mips boards. + * First item is always the number of wired TLB entries, + * following by EntryHi/EntryLo pairs and page mask. + * Since everything must be quad-aligned (8) we insert + * some dummy zeros. + */ + +/* + * Address table of mapping tables for supported Mips boards. + * Add your own stuff here but don't forget to define your + * target system in bootinfo.h + */ + +map0table: PTR map0_dummy # machtype = unknown + PTR map0_rpc # Deskstation rPC44 + PTR map0_tyne # Deskstation Tyne + PTR map0_pica61 # Acer Pica-61 + PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030) + +map0_dummy: .word 0 # 0 entries + + .align 3 +/* + * Initial mappings for Deskstation rPC boards. + * RB: Untested goodie - I don't have such a board. + */ +map0_rpc: .word 2 # no. of wired TLB entries + .word 0 # pad for alignment + +MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache +MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space + +/* + * Initial mappings for Deskstation Tyne boards. + */ +map0_tyne: .word 2 # no. of wired TLB entries + .word 0 # pad for alignment + +MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache +MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space + +/* + * Initial mapping for ACER PICA-61 boards. + * FIXME: These are rather preliminary since many drivers, such as serial, + * parallel, scsi and ethernet need some changes to distinguish between "local" + * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped + * to the same location as the bios maps it to. Console driver has been changed + * accordingly (new video type: VIDEO_TYPE_PICA_S3). + * FIXME: Remove or merge some of the mappings. + */ +map0_pica61: .word 7 # no. wired TLB entries + .word 0 # dummy + +MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # Local I/O space +MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # Interrupt source register +MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # Local video control +MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # Extended video control +MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # Local video memory (BIOS mapping) +MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # ISA I/O and ISA memory space (both 16M) +MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # PCR (???) + +/* + * Initial mapping for Mips Magnum 4000PC systems. + * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-) + * FIXME: Remove or merge some of the mappings. + */ + +map0_magnum4000: + .word 8 # no. wired TLB entries + .word 0 # dummy + +MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, 0x7e000) # 0 +MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, 0x1e000) # 1 local I/O +MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, 0) # 2 IRQ source +MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, 0x1fe000) # 3 local video ctrl +MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, 0x1fe000) # 4 ext. video ctrl +MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, 0x7fe000) # 5 local video mem. +MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, 0x1ffe000) # 6 ISA I/O and mem. +MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, 0) # 7 PCR + + + .text + + .org 0x1000 + .globl swapper_pg_dir +swapper_pg_dir = . + (KSEG1-KSEG0) + +/* + * The page tables are initialized to only 4MB here - the final page + * tables are set up later depending on memory size. + */ + .org 0x2000 + EXPORT(pg0) + + .org 0x3000 + EXPORT(empty_bad_page) + + .org 0x4000 + EXPORT(empty_bad_page_table) + + .org 0x5000 + EXPORT(empty_zero_page) + + .org 0x6000 + EXPORT(invalid_pte_table) + + .org 0x7000 + +/* + * 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). + */ + EXPORT(floppy_track_buffer) + .fill 512*2*36,1,0 + + EXPORT(cache_error_buffer) + .fill 32*4,1,0 + + .data + EXPORT(kernelsp) + PTR 0 |