NanoPayload

stage2/entry.S

145:c39fcc82cc15
2016-02-28 Paul Boddie Introduced kernel regions for task register storage. Removed the invoke_task function.
     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 .extern current_registers    23 .extern current_stack_pointer    24 .globl _tlb_entry    25 .globl _exc_entry    26 .globl _irq_entry    27 .globl _end_entries    28 .set noreorder    29     30 /* NOTE: Duplicated from cpu.h. */    31     32 #define page_table_start 0x80040000    33 #define page_table_task_size_log2 15    34     35 _tlb_entry:    36 	/* Get the bad address. */    37     38 	mfc0 $k0, $10				/* CP0_ENTRYHI */    39 	nop    40 	andi $k1, $k0, 0xff			/* ASID */    41     42 	/* For ASID == 0... */    43     44 	beqz $k1, _tlb_entry_direct    45 	nop    46     47 	/* For addresses over 0x00080000... */    48     49 	li $k1, 0xfff80000    50 	and $k1, $k0, $k1    51 	bnez $k1, _tlb_entry_direct    52 	nop    53     54 	/* Otherwise, load the page table entries. */    55     56 	andi $k1, $k0, 0xff			/* ASID */    57 	sll $k1, $k1, page_table_task_size_log2	/* [ASID] */    58 	li $k0, page_table_start		/* page_table */    59 	add $k0, $k0, $k1			/* page_table[ASID] */    60     61 	mfc0 $k1, $4				/* CP0_CONTEXT */    62 	nop    63 	srl $k1, $k1, 1				/* use 8 byte - not 16 byte - entries */    64 	add $k0, $k0, $k1			/* page_table[ASID][entry] */    65     66 	lw $k1, 0($k0)				/* page_table[ASID][entry][0] */    67 	mtc0 $k1, $2				/* CP0_ENTRYLO0 */    68 	lw $k1, 4($k0)				/* page_table[ASID][entry][1] */    69 	mtc0 $k1, $3				/* CP0_ENTRYLO1 */    70 						/* page size is 4KB */    71 	mtc0 $zero, $5				/* CP0_PAGEMASK */    72 	nop    73     74 	tlbwr    75 	nop    76 	eret    77 	nop    78     79 _tlb_entry_direct:    80 	/* Otherwise, just translate the address directly. */    81     82 	li $k1, 0xffffe000    83 	and $k0, $k0, $k1			/* VPN2 (8KB resolution) */    84 	srl $k0, $k0, 6				/* PFN (maintain 8KB resolution, bit 6 remaining zero) */    85 	ori $k0, $k0, 0x1e			/* flags */    86     87 	mtc0 $k0, $2				/* CP0_ENTRYLO0 */    88 	ori $k0, $k0, 0x40			/* page size is 4KB (bit 6 set) */    89 	mtc0 $k0, $3				/* CP0_ENTRYLO1 */    90 	nop					/* page size is 4KB */    91 	mtc0 $zero, $5				/* CP0_PAGEMASK */    92 	nop    93     94 	tlbwr    95 	nop    96 	eret    97 	nop    98     99 _exc_entry:   100 	/* Handle TLB refill exceptions. */   101    102 	mfc0 $k0, $13				/* CP0_CAUSE */   103 	li $k1, 0x0000007c   104 	and $k0, $k0, $k1			/* ExcCode << 2 */   105 	srl $k0, $k0, 2				/* ExcCode */   106 	addi $k1, $k0, -2			/* ExcCode == 2 */   107 	beqz $k1, _tlb_entry   108 	addi $k1, $k0, -3			/* ExcCode == 3 */   109 	beqz $k1, _tlb_entry   110 	nop   111 _fail:   112 	b _fail   113 	nop   114    115 _irq_entry:   116 	/* Set the ASID. */   117    118 	mtc0 $zero, $10				/* CP0_ENTRYHI */   119 	nop   120    121 	/* Obtain the kernel global offset table. */   122    123 	move $k0, $gp   124 	lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)   125 	ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)   126    127 	/* Obtain a store of registers for the current task. */   128    129 	la $k1, current_registers   130 	lw $k1, 0($k1)   131    132 	/* Save registers that the assembler wants to trash. */   133    134 	sw $t9, 100($k1)   135 	sw $k0, 104($k1)			/* old gp */   136 	sw $ra, 112($k1)   137    138 	/* Record the stack pointer. */   139    140 	la $k1, current_stack_pointer   141 	lw $k1, 0($k1)				/* &stack_pointers[current_task] */   142 	sw $sp, 0($k1)   143    144 	/* Switch to the kernel stack. */   145    146 	li $sp, 0x80070000   147    148 	/* Invoke the rest of the interrupt handling process. */   149    150 	la $k0, interrupt_handler   151 	jr $k0   152 	nop   153    154 _end_entries:   155    156 .set reorder