NanoPayload

stage2/entry.S

141:9e9d063cdfd1
2016-02-27 Paul Boddie Added a generic exception handler to handle TLB misses during exceptions.
     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 .text    21 .extern interrupt_handler    22 .globl _tlb_entry    23 .globl _exc_entry    24 .globl _irq_entry    25 .globl _end_entries    26 .set noreorder    27     28 /* NOTE: Duplicated from cpu.h. */    29     30 #define page_table_start 0x00040000    31 #define page_table_task_size_log2 15    32     33 _tlb_entry:    34 	/* Get the bad address. */    35     36 	mfc0 $k0, $10				/* 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 	/* For addresses over 0x00080000... */    46     47 	li $k1, 0xfff80000    48 	and $k1, $k0, $k1    49 	bnez $k1, _tlb_entry_direct    50 	nop    51     52 	/* Otherwise, load the page table entries. */    53     54 	andi $k1, $k0, 0xff			/* ASID */    55 	sll $k1, $k1, page_table_task_size_log2	/* [ASID] */    56 	li $k0, page_table_start		/* page_table */    57 	add $k0, $k0, $k1			/* page_table[ASID] */    58     59 	mfc0 $k1, $4				/* CP0_CONTEXT */    60 	nop    61 	srl $k1, $k1, 1				/* use 8 byte - not 16 byte - entries */    62 	add $k0, $k0, $k1			/* page_table[ASID][entry] */    63     64 	lw $k1, 0($k0)				/* page_table[ASID][entry][0] */    65 	mtc0 $k1, $2				/* CP0_ENTRYLO0 */    66 	lw $k1, 4($k0)				/* page_table[ASID][entry][1] */    67 	mtc0 $k1, $3				/* CP0_ENTRYLO1 */    68 						/* page size is 4KB */    69 	mtc0 $zero, $5				/* CP0_PAGEMASK */    70 	nop    71     72 	tlbwr    73 	nop    74 	eret    75 	nop    76     77 _tlb_entry_direct:    78 	/* Otherwise, just translate the address directly. */    79     80 	li $k1, 0xffffe000    81 	and $k0, $k0, $k1			/* VPN2 (8KB resolution) */    82 	srl $k0, $k0, 6				/* PFN (maintain 8KB resolution, bit 6 remaining zero) */    83 	ori $k0, $k0, 0x1e			/* flags */    84     85 	mtc0 $k0, $2				/* CP0_ENTRYLO0 */    86 	ori $k0, $k0, 0x40			/* page size is 4KB (bit 6 set) */    87 	mtc0 $k0, $3				/* CP0_ENTRYLO1 */    88 	nop					/* page size is 4KB */    89 	mtc0 $zero, $5				/* CP0_PAGEMASK */    90 	nop    91     92 	tlbwr    93 	nop    94 	eret    95 	nop    96     97 _exc_entry:    98 	/* Handle TLB refill exceptions. */    99    100 	mfc0 $k0, $13				/* CP0_CAUSE */   101 	li $k1, 0x0000007c   102 	and $k0, $k0, $k1			/* ExcCode << 2 */   103 	srl $k0, $k0, 2				/* ExcCode */   104 	addi $k1, $k0, -2			/* ExcCode == 2 */   105 	beqz $k1, _tlb_entry   106 	addi $k1, $k0, -3			/* ExcCode == 3 */   107 	beqz $k1, _tlb_entry   108 	nop   109 _fail:   110 	b _fail   111 	nop   112    113 _irq_entry:   114 	/* Save registers that the assembler wants to trash. */   115    116         sw $t9, -100($sp)   117         sw $gp, -104($sp)   118         sw $ra, -112($sp)   119    120 	lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)   121 	ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)   122 	la $k0, interrupt_handler   123 	jr $k0   124 	nop   125    126 _end_entries:   127    128 .set reorder