NanoPayload

stage2/entry.S

202:934658b3556d
2016-10-02 Paul Boddie Introduced a separate initial tasks manifest.
     1 /*     2  * Interrupt and TLB miss handling support.     3  *     4  * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software: you can redistribute it and/or modify     7  * it under the terms of the GNU General Public License as published by     8  * the Free Software Foundation, either version 3 of the License, or     9  * (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.    18  */    19     20 #include "memory.h"    21 #include "mips.h"    22     23 .text    24 .extern interrupt_handler    25 .extern current_registers    26 .extern current_stack_pointer    27 .globl _tlb_entry    28 .globl _exc_entry    29 .globl _irq_entry    30 .globl _end_entries    31 .set noreorder    32     33 _tlb_entry:    34 	/* Get the bad address. */    35     36 	mfc0 $k0, CP0_ENTRYHI    37 	nop    38 	andi $k1, $k0, 0xff			/* ASID */    39     40 	/* For ASID == 0... */    41     42 	beqz $k1, _tlb_entry_direct    43 	nop    44     45 	/* Otherwise, load the page table entries. */    46     47 	andi $k1, $k0, 0xff			/* ASID */    48 	li $k0, STAGE2_PAGE_TABLE_TASK    49 	mul $k0, $k0, $k1			/* [ASID] (ASID * STAGE2_PAGE_TABLE_TASK) */    50 	li $k1, STAGE2_PAGE_TABLE		/* page_table */    51 	addu $k1, $k0, $k1			/* page_table[ASID] */    52     53 	mfc0 $k0, CP0_CONTEXT    54 	nop    55 	srl $k0, $k0, 1				/* use 8 byte - not 16 byte - entries */    56 	addu $k0, $k0, $k1			/* page_table[ASID][entry] */    57     58 	lw $k1, 0($k0)				/* page_table[ASID][entry][0] */    59 	mtc0 $k1, CP0_ENTRYLO0    60     61 	lw $k1, 4($k0)				/* page_table[ASID][entry][1] */    62 	mtc0 $k1, CP0_ENTRYLO1    63 						/* page size is 4KB */    64 	mtc0 $zero, CP0_PAGEMASK    65 	nop    66     67 	tlbwr    68 	nop    69     70 	eret    71 	nop    72     73 _tlb_entry_direct:    74 	/* Otherwise, just translate the address directly. */    75     76 	li $k1, 0xffffe000    77 	and $k0, $k0, $k1			/* VPN2 (8KB resolution) */    78 	srl $k0, $k0, 6				/* PFN (maintain 8KB resolution, bit 6 remaining zero) */    79 	ori $k0, $k0, 0x1e			/* flags */    80     81 	mtc0 $k0, CP0_ENTRYLO0    82 	ori $k0, $k0, 0x40			/* page size is 4KB (bit 6 set) */    83 	mtc0 $k0, CP0_ENTRYLO1    84 	nop					/* page size is 4KB */    85 	mtc0 $zero, CP0_PAGEMASK    86 	nop    87     88 	tlbwr    89 	nop    90     91 	eret    92 	nop    93     94 _exc_entry:    95 	/* Handle TLB refill exceptions. */    96     97 	mfc0 $k0, CP0_CAUSE    98 	li $k1, 0x0000007c    99 	and $k0, $k0, $k1			/* ExcCode << 2 */   100 	srl $k0, $k0, 2				/* ExcCode */   101 	addi $k1, $k0, -2			/* ExcCode == 2 */   102 	beqz $k1, _tlb_entry   103 	addi $k1, $k0, -3			/* ExcCode == 3 */   104 	beqz $k1, _tlb_entry   105 	nop   106 _fail:   107 	b _fail   108 	nop   109    110 _irq_entry:   111 	/* Set the ASID. */   112    113 	mtc0 $zero, CP0_ENTRYHI   114 	nop   115    116 	/* Obtain the kernel global offset table. */   117    118 	move $k0, $gp   119 	lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)   120 	ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)   121    122 	/* Obtain a store of registers for the current task. */   123    124 	la $k1, current_registers   125 	lw $k1, 0($k1)   126    127 	/* Save registers that the assembler wants to trash. */   128    129 	sw $t9, 100($k1)   130 	sw $k0, 104($k1)			/* old gp */   131 	sw $ra, 112($k1)   132    133 	/* Record the stack pointer. */   134    135 	la $k1, current_stack_pointer   136 	lw $k1, 0($k1)				/* &stack_pointers[current_task] */   137 	sw $sp, 0($k1)   138    139 	/* Switch to the kernel exception stack. */   140    141 	li $sp, STAGE2_EXCEPTION_STACK   142    143 	/* Invoke the rest of the interrupt handling process. */   144    145 	la $k0, interrupt_handler   146 	jr $k0   147 	nop   148    149 _end_entries:   150    151 .set reorder