NanoPayload

Annotated stage2/entry.S

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