NanoPayload

stage2/entry.S

175:8e7b3cc4a268
2016-04-25 Paul Boddie Attempted to simplify region allocation by putting the object table copy in a completely separate location.
     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 .extern _shared_end    25 .globl _tlb_entry    26 .globl _exc_entry    27 .globl _irq_entry    28 .globl _end_entries    29 .globl _enter_task    30 .set noreorder    31     32 #include "paging.h"    33     34 _tlb_entry:    35 	/* Get the bad address. */    36     37 	mfc0 $k0, $10				/* CP0_ENTRYHI */    38 	nop    39 	andi $k1, $k0, 0xff			/* ASID */    40     41 	/* For ASID == 0... */    42     43 	beqz $k1, _tlb_entry_direct    44 	nop    45     46 	/* For addresses beyond the program and data... */    47     48 	lui $k1, %hi(_shared_end - 0x80000000)    49 	ori $k1, $k1, %lo(_shared_end - 0x80000000)    50 	sltu $k1, $k1, $k0    51 	bnez $k1, _tlb_entry_direct    52 	nop    53     54 _tlb_entry_table:    55 	/* Otherwise, load the page table entries. */    56     57 	andi $k1, $k0, 0xff			/* ASID */    58 	li $k0, page_table_task_size    59 	mul $k0, $k0, $k1			/* [ASID] (ASID * page_table_task_size) */    60 	li $k1, page_table_start		/* page_table */    61 	addu $k1, $k0, $k1			/* page_table[ASID] */    62     63 	mfc0 $k0, $4				/* CP0_CONTEXT */    64 	nop    65 	srl $k0, $k0, 1				/* use 8 byte - not 16 byte - entries */    66 	addu $k0, $k0, $k1			/* page_table[ASID][entry] */    67     68 	lw $k1, 0($k0)				/* page_table[ASID][entry][0] */    69 	mtc0 $k1, $2				/* CP0_ENTRYLO0 */    70     71 	lw $k1, 4($k0)				/* page_table[ASID][entry][1] */    72 	mtc0 $k1, $3				/* CP0_ENTRYLO1 */    73 						/* page size is 4KB */    74 	mtc0 $zero, $5				/* CP0_PAGEMASK */    75 	nop    76     77 	tlbwr    78 	nop    79     80 	j _tlb_exit    81 	nop    82     83 _tlb_entry_direct:    84 	/* Otherwise, just translate the address directly. */    85     86 	li $k1, 0xffffe000    87 	and $k0, $k0, $k1			/* VPN2 (8KB resolution) */    88 	srl $k0, $k0, 6				/* PFN (maintain 8KB resolution, bit 6 remaining zero) */    89 	ori $k0, $k0, 0x1e			/* flags */    90     91 	mtc0 $k0, $2				/* CP0_ENTRYLO0 */    92 	ori $k0, $k0, 0x40			/* page size is 4KB (bit 6 set) */    93 	mtc0 $k0, $3				/* CP0_ENTRYLO1 */    94 	nop					/* page size is 4KB */    95 	mtc0 $zero, $5				/* CP0_PAGEMASK */    96 	nop    97     98 	tlbwr    99 	nop   100    101 	/* For ASID == 0... */   102    103 	andi $k1, $k0, 0xff			/* ASID */   104 	bnez $k1, _tlb_exit   105 	nop   106 	eret   107 	nop   108    109 _tlb_exit:   110 	/* For ASID != 0... */   111    112 	lui $k0, %hi(_enter_task)   113 	ori $k0, $k0, %lo(_enter_task)   114 	lw $k1, 0($k0)   115 	jr $k1   116 	nop   117    118 _exc_entry:   119 	/* Handle TLB refill exceptions. */   120    121 	mfc0 $k0, $13				/* CP0_CAUSE */   122 	li $k1, 0x0000007c   123 	and $k0, $k0, $k1			/* ExcCode << 2 */   124 	srl $k0, $k0, 2				/* ExcCode */   125 	addi $k1, $k0, -2			/* ExcCode == 2 */   126 	beqz $k1, _tlb_entry   127 	addi $k1, $k0, -3			/* ExcCode == 3 */   128 	beqz $k1, _tlb_entry   129 	nop   130 _fail:   131 	b _fail   132 	nop   133    134 _irq_entry:   135 	/* Set the ASID. */   136    137 	mtc0 $zero, $10				/* CP0_ENTRYHI */   138 	nop   139    140 	/* Obtain the kernel global offset table. */   141    142 	move $k0, $gp   143 	lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)   144 	ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)   145    146 	/* Obtain a store of registers for the current task. */   147    148 	la $k1, current_registers   149 	lw $k1, 0($k1)   150    151 	/* Save registers that the assembler wants to trash. */   152    153 	sw $t9, 100($k1)   154 	sw $k0, 104($k1)			/* old gp */   155 	sw $ra, 112($k1)   156    157 	/* Record the stack pointer. */   158    159 	la $k1, current_stack_pointer   160 	lw $k1, 0($k1)				/* &stack_pointers[current_task] */   161 	sw $sp, 0($k1)   162    163 	/* Switch to the kernel stack. */   164    165 	li $sp, 0x80070000   166    167 	/* Invoke the rest of the interrupt handling process. */   168    169 	la $k0, interrupt_handler   170 	jr $k0   171 	nop   172    173 _end_entries:   174    175 .set reorder